put in ignore file

This commit is contained in:
2025-08-10 22:01:36 +10:00
parent c2bf5cad70
commit ba79e8f1c4
151 changed files with 21703 additions and 0 deletions
@@ -0,0 +1,7 @@
using System;
namespace FamilyTreeAPI.Authorization;
[AttributeUsage(AttributeTargets.Method)]
public class AllowAnonymousAttribute : Attribute
{ }
@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FamilyTreeAPI.Authorization;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
// private readonly IList<AdminRole> _roles;
/*
public AuthorizeAttribute(params AdminRole[] roles)
{
_roles = roles ?? new AdminRole[] { };
}
*/
public void OnAuthorization(AuthorizationFilterContext context)
{
// skip authorization if action is decorated with [AllowAnonymous] attribute
var allowAnonymous = context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any();
if (allowAnonymous)
return;
// authorization
// var user = (User)context.HttpContext.Items["User"];
// if (user == null || (_roles.Any() && !_roles.Contains(user.Role)))
// {
// not logged in or role not authorized
// context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
//}
}
}
@@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Linq;
using System.Threading.Tasks;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Authorization;
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;
public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}
public async Task Invoke(HttpContext context, IJwtUtils jwtUtils)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (token != null)
{
var user = jwtUtils.ValidateJwtToken(token);
if (user != null)
{
// attach user to context on successful jwt validation
//here to put in the real user
//TODO if you want to add information for User
context.Items["User"] = user;
}
}
await _next(context);
}
}
+111
View File
@@ -0,0 +1,111 @@
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
namespace FamilyTreeAPI.Authorization;
public class JwtUtils : IJwtUtils
{
private readonly AppSettings _appSettings;
public JwtUtils(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
public string GenerateJwtToken(UserDto user)
{
// generate token that is valid for 2 days
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] {
new Claim("id", user.Id.ToString()),
new Claim("subject", user.Username),
new Claim("firstName", user.FirstName + " " + user.LastName)
{
}
//add more if we need it
}
),
Expires = DateTime.UtcNow.AddDays(2),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
// get back id and username. in subject
public UserDto? ValidateJwtToken(string token)
{
if (token == null)
return null;
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
// var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value); //old
int userId = 0;
string username = "";
string firstName = "";
Claim claim;
for (int i = 0; i< jwtToken.Claims.Count(); i++)
{
claim = jwtToken.Claims.ElementAt(i);
if (claim.Type == "id")
{
userId = int.Parse(claim.Value);
}
else if (claim.Type == "subject")
{
username = claim.Value;
}
else if (claim.Type == "firstName")
{
firstName = claim.Value;
}
if (!string.IsNullOrEmpty(username)
&& !string.IsNullOrEmpty(firstName)
&& userId > 0)
{
break;
}
}
UserDto user = new UserDto();
user.Id = userId;
user.Username = username;
user.FirstName = firstName;
// return user id from JWT token if validation successful
return user;
}
catch
{
// return null if validation fails
return null;
}
}
}
@@ -0,0 +1,68 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Mvc;
namespace FamilyTreeAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class LookupController : ControllerBase
{
private readonly ILookup _repo;
public LookupController(ILookup repo)
{
_repo = repo;
}
[HttpGet("[action]")]
public async Task<IActionResult> LoadLookup(string type)
{
var list = await _repo.GetLookupAsync(type);
return Ok(list);
}
[HttpGet("[action]")]
public async Task<IActionResult> LoadLookupEdit(string type)
{
var list = await _repo.GetLookupEditAsync(type);
return Ok(list);
}
[HttpGet("[action]")]
public async Task<IActionResult> GetPersons()
{
var list = await _repo.GetPersonsAsync();
return Ok(list);
}
[HttpGet("[action]")]
public async Task<IActionResult> GetStaffs()
{
var list = await _repo.GetStaffAsync();
return Ok(list);
}
[HttpPost]
public async Task<IActionResult> Lookup([FromBody] LookupEditDto model)
{
//var currentUser = (User?)(HttpContext.Items["User"]);
//if (null == currentUser)
// return Unauthorized(new { message = "Unauthorized" });
var response = await _repo.SaveLookupAsync(model);
return Ok(response);
}
[HttpGet]
public async Task<IActionResult> Lookup(int id, string type)
{
//lookup/id?type='abc'
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _repo.GetLookupEditByIdAsync(id, type);
return Ok(retval);
}
}
}
@@ -0,0 +1,110 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
namespace FamilyTreeAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PersonController : ControllerBase
{
private readonly IPerson _repo;
public PersonController(IPerson repo)
{
_repo = repo;
}
[HttpPost("[action]")]
public async Task<IActionResult> UploadImage(IFormFile file)
{
var keys = Request.Form;
var files = Request.Form.Files;
ResultModel<string> ret = new();
if (files.Count > 0)
{
StringValues familyId = "";
keys.TryGetValue("familyId", out familyId);
UploadCriteria criteria = new();
criteria.File = file;
criteria.FamilyId = familyId;
criteria.FileName = file.FileName;
ret = await _repo.UploadImage(criteria);
}
return Ok(ret);
}
//DeleteUploadFile
[HttpPost("[action]")]
public ActionResult DeleteUploadFile(DeleteFileCriteria criteria)
{
ResultModel<int> ret = new();
if (!string.IsNullOrEmpty(criteria.Filename))
{
ret = _repo.DeleteUploadFile(criteria);
}
return Ok(ret);
}
[HttpPost("[action]")]
public async Task<IActionResult> SearchPerson(PersonCriteria criteria)
{
var list = await _repo.GetPerson(criteria);
return Ok(list);
}
[HttpPost("[action]")]
public async Task<IActionResult> GetChildress(ChildCriteria criteria)
{
var list = await _repo.GetChildren(criteria);
return Ok(list);
}
[HttpPost("[action]")]
public async Task<IActionResult> GetFamilyTreeBy(FamilyCriteria criteria)
{
var list = await _repo.GetFamilyTreeBy(criteria);
return Ok(list);
}
[HttpGet("[action]/{id}")]
public async Task<IActionResult> GetByPersonFamily(int id)
{
var list = await _repo.GetByFamilyAsync(id);
return Ok(list);
}
[HttpGet("[action]/{id}")]
public async Task<IActionResult> GetById(int id)
{
var list = await _repo.GetByIdAsync(id);
return Ok(list);
}
[HttpPost("[action]")]
public async Task<IActionResult> DeleteById(DeleteCriteria<int> criteria)
{
var list = await _repo.DeleteAsync(criteria.Id);
return Ok(list);
}
[HttpPost("[action]")]
public async Task<IActionResult> SavePerson([FromBody] PersonForSave model)
{
//var currentUser = (User?)(HttpContext.Items["User"]);
//if (null == currentUser)
// return Unauthorized(new { message = "Unauthorized" });
var response = await _repo.SaveAsync(model);
return Ok(response);
}
}
}
@@ -0,0 +1,47 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
namespace FamilyTreeAPI.Controllers;
[Route("api/[controller]")]
[ApiController]
public class RelationShipController : ControllerBase
{
private readonly IRelationShipd _repo;
public RelationShipController(IRelationShipd repo)
{
_repo = repo;
}
[HttpGet("[action]/{id}")]
public async Task<IActionResult> GetById(int id)
{
var list = await _repo.GetByIdAsync(id);
return Ok(list);
}
[HttpGet("[action]/{id}")]
public async Task<IActionResult> GetByPersonId(int id)
{
var list = await _repo.GetByPersonIdAsync(id);
return Ok(list);
}
[HttpPost("[action]/{id}")]
public async Task<IActionResult> DeleteById(int id)
{
var list = await _repo.GetByIdAsync(id);
return Ok(list);
}
[HttpPost("[action]")]
public async Task<IActionResult> SaveRelationShip([FromBody] RelationShiftContainer list)
{
//var currentUser = (User?)(HttpContext.Items["User"]);
//if (null == currentUser)
// return Unauthorized(new { message = "Unauthorized" });
var response = await _repo.SaveAsync(list.relationShips);
return Ok(response);
}
}
@@ -0,0 +1,71 @@
using Microsoft.AspNetCore.Mvc;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using System.Threading.Tasks;
namespace FamilyTreeAPI.Controllers;
// [Authorize]
[ApiController]
[Route("api/[controller]")]
public class StaffController : ControllerBase
{
private readonly IStaff _staff;
public StaffController(IStaff staff)
{
_staff = staff;
}
[HttpPost("[action]")]
public async Task<IActionResult> SaveStaff([FromBody] StaffDto model)
{
//var currentUser = (User?)HttpContext.Items["User"];
//if (null == currentUser)
// return Unauthorized(new { message = "Unauthorized" });
var response = await _staff.SaveStaff(model);
return Ok(response);
}
[HttpPost("[action]")]
public async Task<IActionResult> ResetPassStaff([FromBody] ResetPassDto model)
{
//var currentUser = (User?)HttpContext.Items["User"];
//if (null == currentUser)
// return Unauthorized(new { message = "Unauthorized" });
var response = await _staff.ResetPassword(model);
return Ok(response);
}
[HttpPost("[action]")]
public async Task<IActionResult> SearchStaff([FromBody] StaffCriteria criteria)
{
var retval = await _staff.GetStaff(criteria);
return Ok(retval);
}
[HttpGet("{id}")]
public async Task<IActionResult> Staff( int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _staff.GetStaffById(id);
return Ok(retval);
}
[HttpPost("[action]")]
public async Task<IActionResult> DeleteStaff(DeleteCriteria<int> criteria)
{
var currentUser = (UserDto?)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
var retval = await _staff.Delete(criteria.Id);
return Ok(retval);
}
}
@@ -0,0 +1,73 @@
using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Controllers;
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("[action]")]
public async Task<IActionResult> Login([FromBody] AuthenticateRequest model)
{
string remoteIpAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
var response = await _userService.Login(model);
return Ok(response);
}
//[AllowAnonymous]
//[HttpPost("[action]")]
//public async Task<IActionResult> LoginAD(AuthenticateRequest model)
//{
// var response = await _userService.LoginAD(model);
// return Ok(response);
//}
[AllowAnonymous]
[HttpPost("[action]")]
public async Task<IActionResult> LoginApiAD([FromBody] AuthenticateRequest model)
{
string remoteIpAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
var response = await _userService.LoginApiAD(model, remoteIpAddress);
return Ok(response);
}
[HttpPost("[action]")]
public async Task<IActionResult> Logout()
{
var currentUser = (UserDto)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
string token = Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
string remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();
var response = await _userService.Logout(token, currentUser, remoteIpAddress);
return Ok(response);
}
//[AllowAnonymous]
//[HttpGet("[action]")]
//public async Task<IActionResult> SearchADStaff(string stafflinkNo)
//{
// var user = await _userService.SearchADStaff(stafflinkNo);
// return Ok(user);
//}
/*
[AllowAnonymous]
[HttpGet("[action]")]
public async Task<ResultModel<User>> SearchADStaff(string stafflinkNo)
{
var user = await _userService.SearchADStaff(stafflinkNo);
return user;
}
*/
}
+105
View File
@@ -0,0 +1,105 @@
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.EntityFrameworkCore;
using System.Data.Common;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
namespace FamilyTreeAPI.Models
{
public partial class FamilyTreeDBContext
{
private enum EnumStaff
{
Id =0,
Firstname,
Lastname,
Email,
Stype,
Active,
Role,
Password
};
private enum EnumStaffWork
{
id =0,
staffid,
description,
startdate,
sactive,
did,
starttime,
stoptime,
task
}
private enum EnumServiceTask
{
id = 0,
staffid,
sdate,
description,
code,
status,
assignTo,
clientid,
serviceno
}
public async Task<List<StaffDto>> LoadStaffAsync(StaffCriteria criteria)
{
List<StaffDto> list = new();
using (DbConnection connect = this.Database.GetDbConnection())
{
DbCommand command = connect.CreateCommand();
command.CommandType = System.Data.CommandType.Text;
command.CommandText = "SELECT * From usp_search_user(:iemail,:ifirstname,:ilastname)";
var loginParam = command.CreateParameter();
loginParam.ParameterName = "iemail";
loginParam.Value = string.IsNullOrEmpty(criteria.Email) ? "" : criteria.Email;
var fistnameParam = command.CreateParameter();
fistnameParam.ParameterName = "ifirstname";
fistnameParam.Value = string.IsNullOrEmpty(criteria.FirstName) ? "" : criteria.FirstName;
var surnameParam = command.CreateParameter() ;
surnameParam.ParameterName = "ilastname";
surnameParam.Value = string.IsNullOrEmpty(criteria.LastName) ? "" : criteria.LastName;
command.Parameters.Add(loginParam);
command.Parameters.Add(fistnameParam);
command.Parameters.Add(surnameParam);
await connect.OpenAsync();
DbDataReader reader = await command.ExecuteReaderAsync();
StaffDto staff;
int idx = 0;
while (reader.Read())
{
staff = new();
idx = (int)EnumStaff.Id;
staff.Id = reader.GetFieldValue<int>(idx);
idx = (int)EnumStaff.Firstname;
staff.Firstname = reader.GetFieldValue<string?>(idx);
idx = (int) EnumStaff.Lastname;
staff.Lastname = reader.GetFieldValue<string?>(idx);
idx = (int)EnumStaff.Email;
staff.Email = reader.GetFieldValue<string?>(idx);
idx = (int)EnumStaff.Active;
staff.Active = reader.GetFieldValue<bool?>(idx);
idx = (int)EnumStaff.Role;
staff.RoleType = reader.GetFieldValue<int?>(idx);
idx = (int)EnumStaff.Password;
if (!reader.IsDBNull(idx))
staff.Password = reader.GetFieldValue<string?>(idx);
list.Add(staff);
}
}
return list;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
# This stage is used when running from VS in fast mode (Default for Debug configuration)
#FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
ARG BUILD_CONFIGURATION=Release
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["FamilyTreeAPI/FamilyTreeAPI.csproj", "FamilyTreeAPI/"]
COPY ["CommonAD/CommonAD.csproj", "CommonAD/"]
RUN dotnet restore "./FamilyTreeAPI/FamilyTreeAPI.csproj"
COPY . .
WORKDIR "/src/FamilyTreeAPI"
RUN dotnet build "./FamilyTreeAPI.csproj" -c Release -o /app/build
# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
RUN dotnet publish "./FamilyTreeAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
ENV ASPNETCORE_HTTP_PORTS=80
EXPOSE 80
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "FamilyTreeAPI.dll"]
+18
View File
@@ -0,0 +1,18 @@
namespace FamilyTreeAPI.Entities;
public class AppSettings
{
public string Secret { get; set; }
public string SQLConnectionString { get; set; }
public string LoginWebAPI { get; set; }
public string ClientURL { get; set; }
}
/*
entity.HasOne(d => d.Staff)
.WithMany(p => p.Staffworks)
.HasForeignKey(d => d.Staffid)
.HasConstraintName("staffwork_staffid_fkey")
.OnDelete(DeleteBehavior.ClientCascade);
*/
@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace FamilyTreeAPI.Entities;
public class AuthenticateRequest
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
// public string Lhd { get; set; }
}
@@ -0,0 +1,35 @@
namespace FamilyTreeAPI.Entities;
public class AuthenticateResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public string Token { get; set; }
public string Email { get; set; }
public string? Department { get; set; }
public string? Phone { get; set; }
public string? Position { get; set; }
public string? ManagerEmail { get; set; }
public int Role { get; set; }
public AuthenticateResponse(UserDto user, string token, int role)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Username = user.Username;
Email = user.Email;
Department = user.Department;
Position = user.Position;
ManagerEmail = user.ManagerEmail;
Role = role;
Token = token;
Phone = user.Phone;
}
}
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FamilyTreeAPI.Entities;
public class FileContent
{
public byte[] Content { get; set; }
public string FileName { get; set; }
}
public class UploadCriteria
{
public string FileName { get; set; }
public string FamilyId { get; set; }
public IFormFile File { get; set; }
}
public class DeleteFileCriteria
{
public int FamilyId { get; set; }
public string Filename { get; set; }
}
+16
View File
@@ -0,0 +1,16 @@
namespace FamilyTreeAPI.Entities;
public class LookupDto
{
public int Id { get; set; } = 0;
public string CodeId { get; set; }
public string Description { get; set; }
}
public class LookupEditDto
{
public int Id { get; set; } = 0;
public string CodeId { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public string Type { get; set; }
}
+53
View File
@@ -0,0 +1,53 @@
namespace FamilyTreeAPI.Entities;
public class ChildCriteria
{
public int FatherId { get; set; }
public int MotherId { get; set; }
}
public class FamilyCriteria
{
public bool UseFather { get; set; }
public bool UseMother { get; set; }
}
public class PersonCriteria
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonForSave
{
public PersonDto Person { get; set; }
public string? FormData { get; set; }
public string? FileName { get; set; }
}
public partial class PersonDto
{
public PersonDto()
{
}
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string? Image { get; set; }
public string? Sex { get; set; }
public string? Address { get; set; }
public bool? Alive { get; set; }
public string? dob { get; set; }
public int? FatherId { get; set; }
public int? MotherId { get; set; }
public List<RelationShipDto>? RelationShips { get; set; }
}
@@ -0,0 +1,16 @@
namespace FamilyTreeAPI.Entities;
public class RelationShiftContainer
{
public int familyId {get; set;}
public List<RelationShipDto> relationShips {get; set;}
}
public class RelationShipDto
{
public enumState State { get; set; }
public int Id { get; set; }
public int PersonId { get; set; }
public int RelatePersonId { get; set; }
}
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FamilyTreeAPI.Entities;
public enum enumState
{
Delete = -1,
NoChange = 0,
New = 1,
Modify = 2,
}
public class ResultModel<T>
{
public T Data { get; set; }
public int StatusCode { get; set; }
public string Message { get; set; }
}
public class DeleteCriteria<T>
{
public T Id { get; set; }
}
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace FamilyTreeAPI.Entities;
public partial class StaffCriteria
{
public string Email { get; set; } = null!;
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
public partial class StaffDto
{
public int Id { get; set; }
public string? Phone { get; set; } = null!;
public string? Firstname { get; set; }
public string? Lastname { get; set; }
public string? Password { get; set; }
public string? Email { get; set; }
public int? Type { get; set; }
public bool? Active { get; set; }
public int? RoleType { get; set; }
}
public partial class ResetPassDto
{
public int Id { get; set; }
public string Password { get; set; } = null!;
}
+15
View File
@@ -0,0 +1,15 @@
namespace FamilyTreeAPI.Entities;
public class TreeNode<T>
{
public string? Label { get; set; }
public T? Data { get; set; }
public List<TreeNode<T>>? Children { get; set; }
public string? Icon { get; set; }
public bool? Checked { get; set; }
public bool? Leaf { get; set; }
public bool? Expanded { get; set; }
public string? Type { get; set; }
public string? Key { get; set; }
public bool? Loading { get; set; }
}
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FamilyTreeAPI.Entities;
/*
* ROLE ID
* Normal = 1,
Admin = 2,
Manager =3,
*/
public class UserDto
{
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Username { get; set; }
public string? Department { get; set; }
public string? Phone { get; set; }
public string? Position { get; set; }
public string? ManagerEmail { get; set; }
public int Role { get; set; }
}
+38
View File
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Models_old\**" />
<Content Remove="Models_old\**" />
<EmbeddedResource Remove="Models_old\**" />
<None Remove="Models_old\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HotChocolate.AspNetCore" Version="15.1.6" />
<PackageReference Include="HotChocolate.Data.EntityFramework" Version="15.1.6" />
<PackageReference Include="HotChocolate.Pagination.EntityFramework" Version="14.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="SpreadsheetLight" Version="3.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
</ItemGroup>
</Project>
@@ -0,0 +1,19 @@
using FamilyTreeAPI.Models;
namespace FamilyTreeAPI.GraphQL.Query
{
public class QueryFamilyTree
{
[UsePaging]
[UseProjection]
[UseFiltering]
[UseSorting]
public IQueryable<Person> GetPersons([Service] FamilyTreeDBContext dBContext) => dBContext.Persons;
[UsePaging]
[UseProjection]
[UseFiltering]
[UseSorting]
public IQueryable<staff> GetStaffs([Service] FamilyTreeDBContext dBContext) => dBContext.staff;
}
}
+28
View File
@@ -0,0 +1,28 @@
namespace FamilyTreeAPI.Helper
{
public class Helpers
{
public static string? DateToStr(DateTime? date)
{
string? result = null;
if (date.HasValue)
{
result = date.Value.ToString("yyyy-MM-dd");
}
return result;
}
public static DateTime? DateToDateTime(string? date)
{
DateTime? result = null;
if (!string.IsNullOrEmpty(date))
{
DateTime dt;
if (DateTime.TryParse(date, out dt))
{
result = dt;
}
}
return result;
}
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IJwtUtils
{
public string GenerateJwtToken(UserDto user);
public UserDto? ValidateJwtToken(string token);
}
+16
View File
@@ -0,0 +1,16 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface ILookup
{
Task<ResultModel<int>> SaveLookupAsync(LookupEditDto lookup);
Task<ResultModel<List<LookupDto>>> GetLookupAsync(string type);
Task<ResultModel<Dictionary<string, LookupDto>>> GetLookupDicAsync(string type);
Task<ResultModel<List<LookupEditDto>>> GetLookupEditAsync(string type);
Task<ResultModel<LookupEditDto>> GetLookupEditByIdAsync(int codeId, string type);
Task<ResultModel<List<LookupDto>>> GetPersonsAsync();
Task<ResultModel<List<LookupDto>>> GetStaffAsync();
}
+18
View File
@@ -0,0 +1,18 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IPerson
{
Task<ResultModel<TreeNode<string>>> GetByFamilyAsync(int id);
Task<ResultModel<List<TreeNode<string>>>> GetFamilyTreeBy(FamilyCriteria criteria);
Task<ResultModel<List<PersonDto>>> GetChildren(ChildCriteria criteria);
Task<ResultModel<List<PersonDto>>> GetPerson(PersonCriteria criteria);
Task<ResultModel<Dictionary<int,PersonDto>>> GetDicFamily();
Task<ResultModel<PersonDto>> GetByIdAsync(int id);
Task<ResultModel<int>> DeleteAsync(int id);
Task<ResultModel<string>> UploadImage(UploadCriteria criteria);
ResultModel<int> DeleteUploadFile(DeleteFileCriteria criteria);
Task<ResultModel<int>> SaveAsync(PersonForSave dto);
}
@@ -0,0 +1,13 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IRelationShipd
{
Task<ResultModel<int>> SaveAsync(List<RelationShipDto> dto);
//load by personId
Task<ResultModel<List<RelationShipDto>>> GetByPersonIdAsync(int personId);
Task<ResultModel<RelationShipDto>> GetByIdAsync(int Id);
Task<ResultModel<int>> DeleteAsync(int personId);
}
+8
View File
@@ -0,0 +1,8 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IReport
{
// Task<ResultModel<FileContent>> GetMotorVehicleReportAsync(MotorVehicleCriteria criteria);
// Task<ResultModel<FileContent>> GetStaffWorkReportAsync(StaffWorkCriteria criteria);
}
+20
View File
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IStaff
{
Task<ResultModel<Dictionary<int,StaffDto>>> GetDicStaffs();
Task<ResultModel<List<StaffDto>>> GetStaff(StaffCriteria criteria);
Task<ResultModel<StaffDto>> GetStaffById(int id);
Task<ResultModel<int>> SaveStaff(StaffDto code);
Task<ResultModel<int>> ResetPassword(ResetPassDto code);
Task<ResultModel<int>> SaveStaffNew(StaffDto adminUser);
Task<ResultModel<int>> Delete(int id);
}
@@ -0,0 +1,13 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IUserService
{
Task<ResultModel<AuthenticateResponse>> LoginApiAD(AuthenticateRequest model, string remoteIpAddress);
Task<ResultModel<AuthenticateResponse>> Login(AuthenticateRequest model);
Task<ResultModel<int>> Logout(string token, UserDto user, string remoteIpAddress);
// Task<ResultModel<User>> SearchApiStaff(string staffLinkNo);
// Task<ResultModel<User>> SearchADStaff(string staffLinkNo);
}
@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace FamilyTreeAPI.Models
{
public partial class FamilyTreeDBContext : DbContext
{
public FamilyTreeDBContext()
{
}
public FamilyTreeDBContext(DbContextOptions<FamilyTreeDBContext> options)
: base(options)
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
}
public virtual DbSet<Person> Persons { get; set; } = null!;
public virtual DbSet<RelationShip> RelationShips { get; set; } = null!;
public virtual DbSet<Lookup> Lookups { get; set; } = null!;
public virtual DbSet<staff> staff { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>(entity =>
{
entity.ToTable("person");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.Address)
.HasMaxLength(120)
.HasColumnName("address");
entity.Property(e => e.Alive).HasColumnName("alive");
entity.Property(e => e.dob).HasColumnName("dob");
entity.Property(e => e.MotherId).HasColumnName("motherid");
entity.Property(e => e.FatherId).HasColumnName("fatherid");
entity.Property(e => e.FirstName)
.HasMaxLength(70)
.HasColumnName("firstname");
entity.Property(e => e.Sex)
.HasMaxLength(10)
.HasColumnName("sex");
entity.Property(e => e.Image)
.HasMaxLength(300)
.HasColumnName("image");
entity.Property(e => e.LastName)
.HasMaxLength(70)
.HasColumnName("lastname");
entity.Property(e => e.Email)
.HasMaxLength(80)
.HasColumnName("email");
entity.Property(e => e.Phone)
.HasMaxLength(30)
.HasColumnName("phone");
});
modelBuilder.Entity<RelationShip>(entity =>
{
entity.ToTable("relationship");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.RelatePersonId).HasColumnName("relatepersonid");
entity.Property(e => e.PersonId).HasColumnName("personid");
});
modelBuilder.Entity<Lookup>(entity =>
{
entity.ToTable("lookup");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.Code)
.HasMaxLength(10)
.HasColumnName("code");
entity.Property(e => e.Description)
.HasMaxLength(80)
.HasColumnName("description");
entity.Property(e => e.Lactive).HasColumnName("lactive");
entity.Property(e => e.Type).HasMaxLength(20)
.HasColumnName("ltype");
});
modelBuilder.Entity<staff>(entity =>
{
entity.ToTable("staff");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.Email)
.HasMaxLength(80)
.HasColumnName("email");
entity.Property(e => e.Firstname)
.HasMaxLength(70)
.HasColumnName("firstname");
entity.Property(e => e.Lastname)
.HasMaxLength(70)
.HasColumnName("lastname");
entity.Property(e => e.Phone)
.HasMaxLength(30)
.HasColumnName("phone");
entity.Property(e => e.Sactive).HasColumnName("sactive");
entity.Property(e => e.Spassword)
.HasMaxLength(200)
.HasColumnName("spassword");
entity.Property(e => e.Srole).HasColumnName("srole");
entity.Property(e => e.Stype).HasColumnName("stype");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
+14
View File
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
namespace FamilyTreeAPI.Models
{
public partial class Lookup
{
public int Id { get; set; }
public string? Code { get; set; }
public string? Description { get; set; }
public string? Type { get; set; }
public bool? Lactive { get; set; }
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace FamilyTreeAPI.Models
{
public partial class Person
{
public Person()
{
// Servicetasks = new HashSet<Servicetask>();
}
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string? Address { get; set; }
public string? Sex { get; set; }
public string? Image { get; set; }
public bool? Alive { get; set; }
public int? MotherId { get; set; }
public int? FatherId { get; set; }
public DateTime? dob { get; set; }
//public virtual ICollection<Staffwork> Staffworks { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace FamilyTreeAPI.Models;
public class RelationShip
{
public int Id { get; set; }
public int RelatePersonId { get; set; }
public int PersonId { get; set; }
}
+29
View File
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
namespace FamilyTreeAPI.Models
{
public partial class staff
{
public staff()
{
// ServicetaskAssigntoNavigations = new HashSet<Servicetask>();
// ServicetaskStaffs = new HashSet<Servicetask>();
// Staffworks = new HashSet<Staffwork>();
}
public int Id { get; set; }
public string? Firstname { get; set; }
public string? Lastname { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public int? Stype { get; set; }
public int? Srole { get; set; }
public string? Spassword { get; set; }
public bool? Sactive { get; set; }
// public virtual ICollection<Servicetask> ServicetaskAssigntoNavigations { get; set; }
// public virtual ICollection<Servicetask> ServicetaskStaffs { get; set; }
//public virtual ICollection<Staffwork> Staffworks { get; set; }
}
}
+184
View File
@@ -0,0 +1,184 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using DocumentFormat.OpenXml.Office2010.Drawing.Charts;
using FamilyTreeAPI.Authorization;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.GraphQL.Query;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using FamilyTreeAPI.Repository;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
#region Services
var services = builder.Services;
services.AddCors();
services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
var appSettingsSection = builder.Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddHttpContextAccessor();
services.AddScoped<IJwtUtils, JwtUtils>();
services.AddDbContext<FamilyTreeDBContext>(options =>
{
// options.LogTo(s => Console.WriteLine(s));
//options.UseNpgsql(appSettings.SQLConnectionString);
string? conn = builder.Configuration.GetValue<string>("AppSettings:SQLConnectionString");
// options.LogTo(s => Console.WriteLine(s));
if (conn != null)
options.UseNpgsql(conn);
});
services.AddGraphQLServer()
.AddFiltering()
.AddSorting()
.AddProjections()
.RegisterDbContextFactory<FamilyTreeDBContext>()
.AddQueryType<QueryFamilyTree>();
services.AddScoped<ILookup, LookupRepository>();
services.AddScoped<IStaff, StaffRepository>();
services.AddScoped<IRelationShipd,RelationShipRepository>();
services.AddScoped<IPerson, PersonRepository>();
services.AddScoped<IUserService, UserServiceRepository>();
services.AddScoped<IReport, ReportRepository>();
services.AddScoped<Seed>();
/*
public FamilyTreeDBContext(DbContextOptions<FamilyTreeDBContext> options)
: base(options)
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
}
services.AddScoped<IAdminUser, AdminUserRepository>();
services.AddScoped<IMotorVehicles, MotorVehiclesRepository>();
*/
#endregion
#region app
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
try
{
var context = scope.ServiceProvider.GetRequiredService<FamilyTreeDBContext>();
var db = context.Database;
if (db != null)
{
db.Migrate();
db.EnsureCreated();
var staff = context.GetService<Seed>();
int id = staff.InsertOneUser();
if (id < 0)
{
var databaseCreator = (context.GetService<IDatabaseCreator>() as RelationalDatabaseCreator);
if (databaseCreator != null)
{
//if (!databaseCreator.Exists())
databaseCreator.CreateTables();
}
id = staff.InsertOneUser();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
app.UseMiddleware<JwtMiddleware>();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())//
//{
app.UseSwagger();
app.UseSwaggerUI();
//}
// global cors policy
app.UseCors(x => x
.SetIsOriginAllowed(origin => true)
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Content-Disposition")
.AllowCredentials());
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGraphQL();
app.MapControllers();
app.Run();
#endregion
/*
https://www.youtube.com/watch?v=WQFx2m5Ub9M
https://csharptotypescript.azurewebsites.net/
\ services.AddDbContext<BloggingContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("BloggingContext")));
dotnet ef dbcontext scaffold "host=postgresdb;port=5432;Database=FamilyTreeDB;Username=postgres;password=Positive~1" Npgsql.EntityFrameworkCore.PostgreSQL -Schemas schema1 --output-dir Models
PM> Scaffold-DbContext "Host=postgresdb;Port=5432;database=FamilyTreeDB;user id=postgres;Password=Positive~1" Npgsql.EntityFrameworkCore.PostgreSQL -OutputDir Models
*/
/*
graphql
https://www.youtube.com/watch?v=HnXA8RI7Tvc
query {
family {
nodes{
id
firstname
lastname
email
}
}
}
*/
@@ -0,0 +1,41 @@
{
"profiles": {
"FamilyTreeAPI": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5015"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Container (Dockerfile)": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": false
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4559",
"sslPort": 0
}
}
}
+53
View File
@@ -0,0 +1,53 @@
using System.Net.Mail;
namespace FamilyTreeAPI.Repository
{
public class Email
{
public static void SendMail(string smtpServer, string sender, string sendTo,
string header, string message, bool mailPriority = false)
{
if (string.IsNullOrEmpty(smtpServer) && string.IsNullOrEmpty(sender) && string.IsNullOrEmpty(sendTo))
return;
System.Net.Mail.SmtpClient client = new SmtpClient(smtpServer);
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(sender);
var splitEmails = sendTo.Split(';');
foreach (string item in splitEmails)
{
mailMessage.To.Add(item);
}
if (mailPriority)
mailMessage.Priority = MailPriority.High;
// mailMessage.To.Add(sendTo);
mailMessage.Subject = header;
string text = message;
string signature = "";
try
{
text += "<br/>" + signature;
mailMessage.Body = text;
mailMessage.IsBodyHtml = true;
}
catch //(Exception ex)
{
// ErrorLogger.logError(ex, "CPA");
throw;
}
try
{
string userState = "send to fleet manager";
client.SendAsync(mailMessage, userState);
}
catch //(Exception ex)
{
throw;
}
}
}
}
@@ -0,0 +1,278 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace FamilyTreeAPI.Repository
{
public class LookupRepository: ILookup
{
private readonly FamilyTreeDBContext _context;
public LookupRepository(FamilyTreeDBContext context)
{
_context = context;
}
private bool checkDescription(string desc, string type, int id)
{
bool result = false;
if (!string.IsNullOrEmpty(desc))
{
string ldesc = desc.ToLower();
int count = _context.Lookups.Where(x => (x.Code ?? "").ToLower() == ldesc
&& id != x.Id
).ToList().Count();
result = count > 0;
}
return result;
}
public async Task<ResultModel<int>> SaveLookupAsync(LookupEditDto lookup)
{
int result = -1;
int statusCode = 0;
string desc = lookup.Description.Trim();
string error = "";
try
{
Lookup model = null!;
bool ok = !checkDescription(desc, lookup.Type, lookup.Id);
if (ok)
{
if (lookup.Id < 1)
{
model = new();
model.Code = lookup.CodeId;
model.Description = desc;
model.Type = lookup.Type;
model.Lactive = lookup.Active;
_context.Lookups.Add(model);
}
else
{
Lookup? model1 = await _context.Lookups.FindAsync(lookup.Id);
if (model1 != null)
{
model1.Description = desc;
model1.Code = lookup.CodeId;
model1.Lactive = lookup.Active;
}
}
await _context.SaveChangesAsync();
if (model != null)
result = model.Id;
statusCode = 1;
}
else
{
statusCode = 0;
error = "description is already in database";
}
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<LookupEditDto>> GetLookupEditByIdAsync(int id, string type)
{
List<LookupEditDto> resultList;
LookupEditDto item = null!;
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Lookups.Where(x => x.Type == type
&& (x.Id == id))
.Select(item => new LookupEditDto
{
CodeId = string.IsNullOrEmpty(item.Code) ? "0": item.Code,
Active = item.Lactive ?? false,
Id = item.Id,
Description = item.Description ?? ""
})
.ToListAsync();
if (resultList.Count > 0)
item = resultList[0];
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<LookupEditDto>()
{
Data = item,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<List<LookupDto>>> GetLookupAsync(string type)
{
List<LookupDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Lookups.Where(x => x.Type == type && ((x.Lactive ?? false) == true))
.Select(item => new LookupDto { Id = item.Id, CodeId = item.Code ?? "", Description = item.Description ?? "" })
.ToListAsync();
resultList.Sort((x, y) => x.Description.CompareTo(y.Description));
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<LookupDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<Dictionary<string, LookupDto>>> GetLookupDicAsync(string type)
{
Dictionary<string, LookupDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Lookups.Where(x => x.Type == type && ((x.Lactive ?? false) == true))
.Select(item => new LookupDto { Id = item.Id, CodeId = item.Code ?? "", Description = item.Description ?? "" })
.ToDictionaryAsync(x => x.CodeId);
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<Dictionary<string, LookupDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<List<LookupEditDto>>> GetLookupEditAsync(string type)
{
List<LookupEditDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Lookups.Where(x => x.Type == type)
.Select(item => new LookupEditDto
{
Id = item.Id,
Active = item.Lactive ?? false,
CodeId = item.Code ?? "",
Type = item.Type ?? "",
Description = item.Description ?? ""
})
.ToListAsync();
resultList.Sort((x, y) => x.Description.CompareTo(y.Description));
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<LookupEditDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<List<LookupDto>>> GetPersonsAsync()
{
List<LookupDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Persons.Where(x => x.Alive == true)
.Select(item => new LookupDto { Id = item.Id, CodeId = item.Id.ToString(), Description = item.FirstName ?? "" })
.ToListAsync();
resultList.Sort((x, y) => x.Description.CompareTo(y.Description));
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<LookupDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<List<LookupDto>>> GetStaffAsync()
{
List<LookupDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.staff.Where(x => x.Sactive == true)
.Select(item => new LookupDto { Id = item.Id, CodeId = item.Firstname ?? "", Description = item.Lastname ?? "" })
.ToListAsync();
resultList.Sort((x, y) => x.Description.CompareTo(y.Description));
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<LookupDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
}
}
@@ -0,0 +1,657 @@
using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Office.CustomUI;
using DocumentFormat.OpenXml.Office2010.Excel;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Helper;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
namespace FamilyTreeAPI.Repository;
public partial class PersonRepository : IPerson
{
private readonly FamilyTreeDBContext _context;
private readonly IRelationShipd _relationship;
private readonly IHttpContextAccessor _httpContext;
private readonly IConfiguration _config;
const string dateFormat = "yyyy-MM-dd";
public PersonRepository(IConfiguration config, FamilyTreeDBContext context,
IRelationShipd relationship,
IHttpContextAccessor httpContext)
{
_context = context;
_relationship = relationship;
_config = config;
_httpContext = httpContext;
}
private PersonDto FillDto(Person model)
{
PersonDto dto = new();
dto.Id = model.Id;
dto.FirstName = model.FirstName;
dto.LastName = model.LastName;
dto.Email = model.Email;
dto.Address = model.Address;
dto.Phone = model.Phone;
dto.Alive = model.Alive;
dto.Image = model.Image;
dto.FatherId = model.FatherId;
dto.MotherId = model.MotherId;
dto.Sex = model.Sex;
dto.dob = Helpers.DateToStr(model.dob);
/*
dto.AddedOn = model.AddedOn;
dto.RoleType = model.RoleType;
*/
return dto;
}
private Person FillModel(Person model, PersonDto dto)
{
model.FirstName = dto.FirstName;
model.LastName = dto.LastName;
model.Email = dto.Email;
model.Address = dto.Address;
model.Phone = dto.Phone;
model.Alive = dto.Alive;
model.Image = dto.Image;
model.FatherId = dto.FatherId;
model.MotherId = dto.MotherId;
model.Sex = dto.Sex;
model.dob = Helpers.DateToDateTime(dto.dob);
return model;
}
public async Task<ResultModel<Dictionary<int, PersonDto>>> GetDicFamily()
{
Dictionary<int, PersonDto> list = new();
int statuscode = 0;
string error = "";
PersonDto item;
Person jitem;
try
{
//list = await _context.LoadStaffAsync(criteria);
var jlist = await _context.Persons.ToListAsync();
for (int i = 0; i < jlist.Count; i++)
{
jitem = jlist[i];
item = FillDto(jitem);
list.Add(item.Id,item);
}
statuscode = 1;
//list.Sort((x, y) => x.Code.CompareTo(y.Code));
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel< Dictionary<int, PersonDto> > ()
{
Data = list,
StatusCode = statuscode,
Message = error
};
}
private async Task<List<PersonDto>> GetChildrens(int FatherId, int MotherId)
{
List<PersonDto> list = new();
PersonDto item;
Person jitem;
var jlist = await _context.Persons.Where(x =>
(x.MotherId == FatherId && x.FatherId == MotherId) ||
(x.FatherId == FatherId && x.MotherId == MotherId)).ToListAsync();
for (int i = 0; i < jlist.Count; i++)
{
jitem = jlist[i];
item = FillDto(jitem);
list.Add(item);
}
return list;
}
public async Task<ResultModel<List<PersonDto>>> GetChildren(ChildCriteria criteria)
{
List<PersonDto> list = new();
int statuscode = 0;
string error = "";
PersonDto item;
Person jitem;
try
{
//list = await _context.LoadStaffAsync(criteria);
list = await GetChildrens(criteria.FatherId, criteria.MotherId);
statuscode = 1;
//list.Sort((x, y) => x.Code.CompareTo(y.Code));
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<List<PersonDto>>()
{
Data = list,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<List<PersonDto>>> GetPerson(PersonCriteria criteria)
{
List<PersonDto> list = new();
List<Person>? jlist;
int statuscode = 0;
string error = "";
PersonDto item;
Person jitem;
string firstName = criteria.FirstName;
string lastName = criteria.LastName;
int Id = criteria.Id;
try
{
//list = await _context.LoadStaffAsync(criteria);
if (!string.IsNullOrEmpty(firstName))
{
firstName = firstName.ToLower();
jlist = await _context.Persons.Where(x =>
EF.Functions.Like(x.FirstName.ToLower(),firstName + "%")).ToListAsync();
}
else if (!string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(lastName))
{
firstName = firstName.ToLower();
lastName = lastName.ToLower();
jlist = await _context.Persons.Where(x => EF.Functions.Like(x.FirstName.ToLower(),firstName + "%")
&& EF.Functions.Like(x.LastName.ToLower(),lastName + "%")).ToListAsync();
}
else
jlist = await _context.Persons.ToListAsync();
for (int i = 0; i < jlist.Count; i++)
{
jitem = jlist[i];
item = FillDto(jitem);
list.Add(item);
}
statuscode = 1;
//list.Sort((x, y) => x.Code.CompareTo(y.Code));
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<List<PersonDto>>()
{
Data = list,
StatusCode = statuscode,
Message = error
};
}
private async Task<Person> GetPerson(int id)
{
Person rval = await _context.Persons.FindAsync(id);
return rval;
}
public async Task<ResultModel<TreeNode<string>>> GetByFamilyAsync(int id)
{
int statuscode = 0;
string error = "";
string key = "";
string data = "";
string type = "default";
string pName = "";
Person person;
TreeNode<string> citem;
TreeNode<string> child;
TreeNode<string> node = new();
node.Children = new();
PersonDto dto = new();
try
{
var item = await _context.Persons.FindAsync(id);
if (item == null)
{
statuscode = -1;
}
else
{
node.Label = item.FirstName;
node.Key = item.Id.ToString();
node.Type = type;
node.Expanded = true;
node.Data = item.Sex;
statuscode = 1;
dto = FillDto(item);
await GetPartnerChildrens(dto, node);
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<TreeNode<string>> ()
{
Data = node,
StatusCode = statuscode,
Message = error
};
}
private async Task GetPartnerChildrens(PersonDto person, TreeNode<string> node)
{
/*****************************/
ResultModel<List<RelationShipDto>> rlist = await _relationship.GetByPersonIdAsync(person.Id);
List<RelationShipDto> relationShips = rlist.Data;
RelationShipDto relate;
string type = node.Type;
TreeNode<string> child;
PersonDto dto;
Person pe;
int fatherId, motherId;
fatherId = motherId = 0;
string data = person.Sex;
TreeNode<string> citem;
string pName = "";
string key = "";
for (int i = 0; i < relationShips.Count; i++)
{
relate = relationShips[i];
if (relate.PersonId == person.Id)
{
if (data == "M")
{
fatherId = relate.PersonId;
motherId = relate.RelatePersonId;
}
else
{
fatherId = relate.RelatePersonId;
motherId = relate.PersonId;
}
}
else
{
if (data == "M")
{
fatherId = relate.PersonId;
motherId = relate.RelatePersonId;
}
else
{
fatherId = relate.RelatePersonId;
motherId = relate.PersonId;
}
}
//get children
List<PersonDto> children = await GetChildrens(fatherId, motherId);
if (children.Count > 0)
{
if (person.Id != motherId)
{
//kham
if (motherId > 0)
{
pe = await GetPerson(motherId);
pName = pe.FirstName;
key = motherId.ToString();
data = "F";
}
}
else
{
if (fatherId > 0)
{
pe = await GetPerson(fatherId);
pName = pe.FirstName;
key = fatherId.ToString();
data = "M";
}
}
citem = new TreeNode<string>();
citem.Label = pName;
citem.Expanded = true;
citem.Data = data;
citem.Type = type;
citem.Key = key;
citem.Children = new List<TreeNode<string>>();
node.Children.Add(citem);
for (int j = 0; j < children.Count; j++)
{
dto = children[j];
child = new TreeNode<string>();
child.Expanded = true;
child.Type = type;
child.Label = dto.FirstName;
child.Key = dto.Id.ToString();
child.Data = dto.Sex;
child.Children = new();
citem.Children.Add(child);
//get child partner and repeat this.
await GetPartnerChildrens(dto, child);
}
}
}
/*****************************************/
}
public async Task<ResultModel<PersonDto>> GetByIdAsync(int id)
{
int statuscode = 0;
string error = "";
PersonDto dto = new();
try
{
var item = await _context.Persons.FindAsync(id);
if (item == null)
{
statuscode = -1;
}
else
{
dto = FillDto(item);
statuscode = 1;
ResultModel<List<RelationShipDto>> rlist = await _relationship.GetByPersonIdAsync(dto.Id);
dto.RelationShips = rlist.Data;
statuscode = rlist.StatusCode;
error = rlist.Message;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<PersonDto>()
{
Data = dto,
StatusCode = statuscode,
Message = error
};
}
private string GetDateTimeNow()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
/// <summary>
/// need filename to get extension file and family name for id combine to
/// name to table.
/// </summary>
/// <param name="fileName"></param>
/// <param name="familyId"></param>
/// <param name="base64"></param>
private string SaveFile(string fileName, int familyId, string base64)
{
string path = "";
int statusCode = 0;
string error = "";
string sdate = GetCurrentDateTime();
string filename, extention;
filename = extention = "";
int first = base64.IndexOf("base64,") +"base64,".Length;
int last = base64.Length;
string rbase = base64.Substring(first, last - first);
byte[] newBytes = Convert.FromBase64String(rbase);
path = _config["AppSettings:ImageFolder"];
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
extention = System.IO.Path.GetExtension(fileName);
filename = familyId + "_" + sdate + extention;
string fullpath = System.IO.Path.Combine(path, filename);
/*
using (var fileStream = new FileStream(fullpath, FileMode.Create))
{
StreamWriter writer = new StreamWriter(fileStream);
writer.Write(newBytes);
//writer.BaseStream.Write(bytes, 0, bytes.Length);
}
*/
using (MemoryStream ms = new MemoryStream(newBytes))
{
Image image = Image.FromStream(ms);
image.Save(fullpath);
}
return filename;
}
public async Task<ResultModel<int>> SaveAsync(PersonForSave container)
{
int result = default(int);
int statuscode = 0;
string error = "";
HttpContext? httpContext = _httpContext.HttpContext;
string loginName = "";
if (httpContext != null)
{
UserDto? user = (UserDto?)httpContext.Items["User"];
if (user != null)
loginName = user.FirstName + " " + user.LastName;
}
PersonDto item = container.Person;
try
{
Person model;
if (item.Id < 1)
{
model = new();
model = FillModel(model, item);
// model.Active = true;
// model.AddedBy = loginName;
// model.AddedOn = DateTime.Now;
_context.Persons.Add(model);
var successid = await _context.SaveChangesAsync();
result = model.Id;
if (!string.IsNullOrEmpty(container.FileName))
{
string image = SaveFile(container.FileName, result, container.FormData);
// update the image in table to new
model.Image = image;
await _context.SaveChangesAsync();
}
}
else
{
var model1 = await _context.Persons.FindAsync(item.Id);
if (model1 != null)
{
model1 = FillModel(model1, item);
result = item.Id;
if (!string.IsNullOrEmpty(container.FileName))
{
string image = SaveFile(container.FileName, result, container.FormData);
// update the image in table to new
model1.Image = image;
}
var successid = await _context.SaveChangesAsync();
}
// model.LastModified = DateTime.Now;
// model.LastModifiedId = loginName;
}
statuscode = 1;
if (item.RelationShips != null)
{
ResultModel<int> rresult = await this._relationship.SaveAsync(item.RelationShips);
statuscode = rresult.StatusCode;
error += rresult.Message;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> DeleteAsync(int id)
{
int result = 1;
int statuscode = 0;
string error = "";
try
{
var model = await _context.Persons.FindAsync(id);
if (model != null)
_context.Persons.Remove(model);
var successCount = await _context.SaveChangesAsync();
statuscode = 1;
result = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public Task<ResultModel<string>> UploadImage(UploadCriteria criteria) {
return UploadImagep(criteria);
}
private string GetCurrentDateTime()
{
DateTime now = DateTime.Now;
return now.ToString("yyyyMMdd");
}
private async Task<ResultModel<string>> UploadImagep(UploadCriteria criteria)
{
string path = "";
int statusCode = 0;
string error = "";
string sdate = GetCurrentDateTime();
string filename, extention;
filename = extention = "";
try
{
if (criteria.File.Length > 0)
{
path = _config["AppSettings:ImageFolder"];
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
extention = System.IO.Path.GetExtension(criteria.FileName);
filename = criteria.FamilyId + "_" + sdate + extention;
using (var fileStream = new FileStream(System.IO.Path.Combine(path, filename), FileMode.Create))
{
await criteria.File.CopyToAsync(fileStream);
}
statusCode = 1;
}
else
{
statusCode = -1;
error = "file contain is empty";
}
}
catch (Exception ex)
{
statusCode = -1;
error = ex.Message;
}
return new ResultModel<string>()
{
Data = filename,
StatusCode = statusCode,
Message = error
};
}
public ResultModel<int> DeleteUploadFile(DeleteFileCriteria criteria)
{
int result = -1;
int statusCode = 0;
string error = "";
var filePath = _config["AppSettings:ImageFolder"];
var myfile = filePath + "\\" + criteria.Filename;
try
{
File.Delete(myfile);
result = 1;
statusCode = 1;
Person? model = _context.Persons.Find(criteria.FamilyId);
if (model != null)
{
model.Image = null;
_context.SaveChanges();
}
}
catch (Exception e)
{
result = -1;
statusCode = -1;
error += e.Message;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statusCode,
Message = error
};
}
}
@@ -0,0 +1,139 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
using System.Drawing.Text;
namespace FamilyTreeAPI.Repository;
public partial class PersonRepository
{
private TreeNode<string> PopulateItem(Person model)
{
TreeNode<string> treeNode = new();
treeNode.Label = model.FirstName;
treeNode.Data = model.Id.ToString();
treeNode.Key = model.Id.ToString();
treeNode.Children = new();
return treeNode;
}
private bool UseFamilyCriteria(FamilyCriteria criteria, Person person)
{
bool result = false;
if (criteria.UseFather && criteria.UseMother)
{
result = person.FatherId.GetValueOrDefault(0) == 0
&& person.MotherId.GetValueOrDefault(0) == 0;
}
else if (criteria.UseFather)
{
result = person.FatherId.GetValueOrDefault(0) == 0;
}
else if (criteria.UseMother)
{
result = person.MotherId.GetValueOrDefault(0) == 0;
}
return result;
}
private bool UseChildFamilyCriteria(FamilyCriteria criteria, int id, Person person)
{
bool result = false;
int parentId;
if (criteria.UseFather)
{
parentId = person.FatherId.GetValueOrDefault(0);
result = parentId == id;
}
else if (criteria.UseMother)
{
parentId = person.MotherId.GetValueOrDefault(0);
result = parentId == id;
}
return result;
}
private List<Person> SplitListOfTopLevel(List<Person> list, FamilyCriteria criteria)
{
List<Person> result = new();
Person item;
for (int i = list.Count - 1; i > -1; i--)
{
item = list[i];
if (UseFamilyCriteria(criteria,item))
{
result.Add(item);
list.RemoveAt(i);
}
}
return result;
}
private List<Person> GetParentId(List<Person> list,int id, FamilyCriteria criteria, Func<FamilyCriteria, int, Person, bool> conditionFn)
{
List<Person> result = new();
Person item;
for (int i = list.Count - 1; i > -1; i--)
{
item = list[i];
if (conditionFn(criteria,id, item))
{
result.Add(item);
list.RemoveAt(i);
}
}
return result;
}
private List<TreeNode<string>> PopulateChild(FamilyCriteria criteria,int id, List<Person> childList, Func<FamilyCriteria, int ,Person,bool> conditionFn)
{
Person person;
TreeNode<string> treeNode;
List<TreeNode<string>> list = new();
List<Person> children = GetParentId(childList,id, criteria, conditionFn);
for (int i = 0; i < children.Count; i++)
{
person = children[i];
treeNode = PopulateItem(person);
list.Add(treeNode);
// get children of this one too
treeNode.Children = PopulateChild(criteria, person.Id, childList, UseChildFamilyCriteria);
}
return list;
}
public async Task<ResultModel<List<TreeNode<string>>> > GetFamilyTreeBy(FamilyCriteria criteria)
{
int statusCode = -1;
string error = "";
Person person;
TreeNode<string> treeNode;
List<TreeNode<string>> data = new();
try
{
var personList = await _context.Persons.ToListAsync();
var topList = SplitListOfTopLevel(personList, criteria);
for (int i = 0; i < topList.Count; i++)
{
person = topList[i];
treeNode = PopulateItem(person);
data.Add(treeNode);
treeNode.Children = PopulateChild(criteria, person.Id, personList, UseChildFamilyCriteria);
}
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<TreeNode<string>>>
{
Data = data,
StatusCode = statusCode,
Message = error
};
}
}
@@ -0,0 +1,184 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace FamilyTreeAPI.Repository;
public class RelationShipRepository: IRelationShipd
{
private readonly FamilyTreeDBContext _context;
private readonly IHttpContextAccessor _httpContext;
private readonly IConfiguration _config;
public RelationShipRepository(IConfiguration config, FamilyTreeDBContext context, IHttpContextAccessor httpContext)
{
_context = context;
_config = config;
_httpContext = httpContext;
}
private RelationShip FillModel(RelationShipDto dto, RelationShip model)
{
model.RelatePersonId = dto.RelatePersonId;
model.PersonId = dto.PersonId;
return model;
}
private RelationShipDto FillDto(RelationShip model)
{
RelationShipDto dto = new();
dto.Id = model.Id;
dto.PersonId = model.PersonId;
dto.RelatePersonId = model.RelatePersonId;
return dto;
}
public async Task<ResultModel<int>> SaveAsync(List<RelationShipDto> list)
{
int statusCode = 0;
string error = "";
RelationShipDto item;
RelationShip model;
try
{
for (int i = 0; i < list.Count; i++)
{
item = list[i];
if (item.Id < 1)
{
model = new();
model = FillModel(item, model);
_context.RelationShips.Add(model);
}
else if (item.State == enumState.Modify)
{
RelationShip? RelationShip = await _context.RelationShips.FindAsync(item.Id);
if (RelationShip != null)
{
RelationShip = FillModel(item, RelationShip);
}
}
else if (item.State == enumState.Delete)
{
RelationShip? RelationShip = await _context.RelationShips.FindAsync(item.Id);
if (RelationShip != null)
{
_context.RelationShips.Remove(RelationShip);
}
}
}
statusCode = 1;
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<int>
{
StatusCode = statusCode,
Data = statusCode,
Message = error
};
}
public async Task<ResultModel<List<RelationShipDto>>> GetByPersonIdAsync(int personId)
{
string error = "";
int statusCode = -1;
List<RelationShipDto> list = new();
RelationShipDto dto;
RelationShip model;
try
{
var mlist = await _context.RelationShips.Where(x => x.PersonId == personId).ToListAsync();
for (int i = 0; i < mlist.Count; i++)
{
model = mlist[i];
dto = FillDto(model);
list.Add(dto);
}
var rlist = await _context.RelationShips.Where(x => x.RelatePersonId == personId).ToListAsync();
for (int i = 0; i < rlist.Count; i++)
{
model = rlist[i];
dto = FillDto(model);
list.Add(dto);
}
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<List<RelationShipDto>>
{
StatusCode = statusCode,
Data = list,
Message = error
};
}
public async Task<ResultModel<RelationShipDto>> GetByIdAsync(int Id)
{
string error = "";
int statusCode = -1;
RelationShipDto dto =new();
RelationShip? model;
try
{
model = await _context.RelationShips.FindAsync(Id);
if (model != null)
dto = FillDto(model);
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = -1;
}
return new ResultModel<RelationShipDto>
{
StatusCode = statusCode,
Data = dto,
Message = error
};
}
public async Task<ResultModel<int>> DeleteAsync(int Id)
{
int result = -1;
string error = "";
int statusCode = -1;
try
{
RelationShip? RelationShip = await _context.RelationShips.FindAsync(Id);
if (RelationShip != null)
{
_context.RelationShips.Remove(RelationShip);
}
}
catch (Exception e)
{
error = e.ToString();
statusCode = -1;
}
return new ResultModel<int>
{
StatusCode = statusCode,
Data = result,
Message = error
};
}
}
@@ -0,0 +1,272 @@
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using SpreadsheetLight;
using System.Linq;
using DocumentFormat.OpenXml.Spreadsheet;
namespace FamilyTreeAPI.Repository;
public class ReportRepository : IReport
{
private enum EnumStaffWork
{
Id = 0,
FirstName,
LastName,
StartDate,
startTime,
stopTime,
Task,
Job,
Hour
};
private readonly FamilyTreeDBContext _context;
//private readonly ILookup _lookup;
const string DateTimeFormat = "dd/MM/yyyy HH:mm";
const string TimeFormat = "HH:mm";
const string DateFormat = "dd/MM/yyyy";
private readonly IStaff _staff;
private Dictionary<int, StaffDto> _dstaff;
private readonly ILookup _lookup;
private string DisplayTime(DateTime date)
{
string result = "";
if (date != DateTime.MinValue)
result = date.ToString(TimeFormat);
return result;
}
private string DisplayDateTime(DateTime? date)
{
string result = "";
if (date != DateTime.MinValue)
result = date!.Value.ToString(DateFormat);
return result;
}
private string FormatTime(int hour)
{
string result;
if (hour < 10)
result = "0" + hour.ToString() + ":00";
else
result = hour.ToString() + ":00";
return result;
}
public ReportRepository(FamilyTreeDBContext context, ILookup lookup,IStaff staff)
{
_context = context;
_lookup = lookup;
_staff = staff;
}
// public async Task<ResultModel<FileContent>> GetStaffWorkReportAsync(StaffWorkCriteria criteria)
// {
// //var data = await _lookup.GetLookupDicAsync("TypeOfUse");
// //if (data != null)
// //{
// // this._ServiceTypeDic = data.Data;
// //}
// var rstaff = await _staff.GetDicStaffs();
// if (rstaff.StatusCode == 1)
// _dstaff = rstaff.Data;
// //data = await _lookup.GetLookupDicAsync("Status");
// //if (data != null)
// //{
// // this._StatusDic = data.Data;
// //}
// int statusCode = 1;
// int col = 1;
// int row = 1;
// SLDocument sl = new SLDocument();
// SLStyle styleRed = sl.CreateStyle();
// styleRed.SetFontColor(System.Drawing.Color.Red);
// //first sheetName
// sl.RenameWorksheet(SLDocument.DefaultFirstSheetName, "Staff Work Report");
// SLStyle style = sl.CreateStyle();
// style.SetFontUnderline(DocumentFormat.OpenXml.Spreadsheet.UnderlineValues.Single);
// style.SetFontBold(true);
// style.SetFont("Calibri", 14);
// sl.SetCellStyle(1, 3, style);
// sl.SetRowHeight(1, 1, 25);
// sl.SetCellValue(row++, 3, "Staff Work");
// // sl.SetCellValue(row, 3, "From Date: " + fromDate.ToString(DateFormat) + " - " + toDate.ToString(DateFormat));
// sl.SetCellValue(1, 6, " " + DateTime.Now.ToString("ddd dd/MM/yyyy HH:mm"));
// // sl.SetCellValue(row, 6, "Hospital: " + facility);
// int startTitleRow = 3;
// row = startTitleRow;
// //make the title bold
// style = sl.CreateStyle();
// style.Font.Bold = true;
// sl.SetRowStyle(startTitleRow, style);
// //set it height
// sl.SetRowHeight(startTitleRow, startTitleRow, 25);
// // add the title first
// sl.SetCellValue(row, (int)EnumStaffWork.Id, "Id");
// sl.SetCellValue(row, (int) EnumStaffWork.FirstName, "FirstName");
// sl.SetCellValue(row, (int) EnumStaffWork.LastName, "SurName");
// sl.SetCellValue(row, (int) EnumStaffWork.StartDate, "StartDate");
// sl.SetCellValue(row, (int)EnumStaffWork.startTime, "Start Time");
// sl.SetCellValue(row, (int)EnumStaffWork.stopTime, "Stop Time");
// sl.SetCellValue(row, (int)EnumStaffWork.Hour, "Hour");
// /*
// style = sl.CreateStyle();
// style.SetFontColor(System.Drawing.Color.Blue);
// sl.SetRowStyle(row, style);
// */
// sl.FreezePanes(row, 0); //frozen the row.
// //wrap text on is concession Expiry
// style = sl.CreateStyle();
// style.SetWrapText(true);
// sl.SetColumnStyle(4, style);
// //format date
// // style = sl.CreateStyle();
// //style.FormatCode = DateTimeFormat;
// // sl.SetColumnStyle(1, style);
// //make column width
// sl.SetColumnWidth((int)EnumStaffWork.Id, 10);
// sl.SetColumnWidth((int)EnumStaffWork.FirstName, 30);
// sl.SetColumnWidth((int)EnumStaffWork.LastName, 30);
// sl.SetColumnWidth((int)EnumStaffWork.StartDate, 25);
// sl.SetColumnWidth((int)EnumStaffWork.startTime, 10);
// sl.SetColumnWidth((int)EnumStaffWork.stopTime, 10);
// sl.SetColumnWidth((int)EnumStaffWork.Hour, 20);
// style = sl.CreateStyle();
// style.FormatCode = DateFormat;
// sl.SetColumnStyle(5, style);
// //style = sl.CreateStyle();
// //style.FormatCode = DateTimeFormat;
// //sl.SetColumnStyle(1, style);
// sl.SetColumnWidth(10, 20);
// int startRowFrom = startTitleRow + 1;
//// DateTime ttdate = toDate.ToLocalTime(); //add 1 days so if to inclusive todate 02/09
// var container = await _context.LoadStaffWorkAsync(criteria); //fromDate.ToLocalTime(), ttdate.AddDays(1), typeOfCall);
// var list = container;
// list.Sort((x, y) => x.StartDate.Value.CompareTo(y.StartDate.Value));
// StaffWorkViewDto item;
// DateTime startTime, stopTime;
// double hour =0;
// string fname, lname;
// StaffWorkDetailDto detail;
// for (int i = 0; i < list.Count; i++)
// {
// item = list[i];
// row = i + startRowFrom;
// (startTime, stopTime ) = GetSSTime(item);
// if (item.Details != null)
// for (int j = 0; j < item.Details.Count; j++)
// {
// detail = item.Details[j];
// hour += detail.TotalMinuts();
// }
// (fname, lname) = GetStaffName(item.StaffId.Value);
// sl.SetCellValue(row, (int)EnumStaffWork.StartDate, item.StartDate.Value);
// sl.SetCellValue(row, (int)EnumStaffWork.FirstName, fname);
// sl.SetCellValue(row, (int)EnumStaffWork.LastName, lname);
// sl.SetCellValue(row, (int)EnumStaffWork.startTime, startTime);
// sl.SetCellValue(row, (int)EnumStaffWork.stopTime, stopTime);
// sl.SetCellValue(row, (int)EnumStaffWork.Hour, hour/60);
// }
// byte[] array;
// // sl.SaveAs("C:\\Temp\\Report\\ConcessionValidationDate" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xlsx");
// using (MemoryStream ws = new MemoryStream())
// {
// sl.SaveAs(ws);
// array = ws.ToArray();
// /*
// using (FileStream fs = new FileStream("c:\\temp\\Report\\conReport.xlsx",FileMode.Create,FileAccess.Write))
// {
// ws.WriteTo(fs);
// fs.Close();
// }
// */
// ws.Close();
// }
// var result = new FileContent
// {
// Content = array,
// FileName = "StaffWork_Report" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm") + ".xlsx",
// };
// return new ResultModel<FileContent>
// {
// Data = result,
// StatusCode = statusCode
// };
// }
private (string, string) GetStaffName(int staffId)
{
StaffDto staff;
if (_dstaff.ContainsKey(staffId))
{
staff = _dstaff[staffId];
return ( staff.Firstname ?? "" , staff.Lastname ?? "");
}
return ("","");
}
//private (DateTime firstTime, DateTime lastTime) GetSSTime(StaffWorkViewDto item)
//{
// DateTime sTime, lTime;
// DateTime? value;
// int count = 0;
// sTime = lTime = DateTime.Now;
// List<StaffWorkDetailDto> detail = item.Details ?? new();
// count = detail.Count;
// if (count > 0)
// {
// value = detail[0].StartTime;
// if (value.HasValue)
// {
// sTime = value.Value;
// }
// value = detail[count - 1].StopTime;
// if (value.HasValue)
// {
// lTime = value.Value;
// }
// }
// return (sTime, lTime);
//}
private string GetValue(string item, string text)
{
string result = item;
if (!string.IsNullOrEmpty(text))
result = text;
return result;
}
//private string GetPools(List<string> poolIds)
//{
// string result = "";
// string id;
// for (int i = 0; i < poolIds.Count; i++)
// {
// id = poolIds[i];
// if (this._PoolDic.ContainsKey(id))
// result += _PoolDic[id].Description + ",";
// }
// result = result.Remove(result.Length-1, 1);
// return result;
//}
}
+83
View File
@@ -0,0 +1,83 @@
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace FamilyTreeAPI.Repository;
public class Seed
{
private readonly FamilyTreeDBContext _context;
public Seed(FamilyTreeDBContext context)
{
_context = context;
}
public int InsertOneUser()
{
int id = -1;
//password = password
string txt = " INSERT INTO staff ( " +
"firstname, lastname, email, phone, stype, srole, spassword, sactive) " +
"VALUES" +
" ( 'kham', 'vilaythong', 'kham.vilaythong@gmail.com', '009', 1, 2, 'cGFzc3dvcmQ=', true), " +
" ( 'sy', 'vilaythong', 'sy.vilaythong@gmail.com', '007', 1, 2, 'cGFzc3dvcmQ=', true), " +
" ( 'Hung', 'Nguyen', 'hung.gnuyen@gmail.com', '008', 1, 2, 'cGFzc3dvcmQ=', true); ";
string workertxt = "INSERT INTO person ( firstname, lastname,email,phone,address,dob ,alive, fatherId, image, sex)" +
"VALUES " +
" ('Ho 1','Tran', 'Ho.Tran@hotmail.com', '002', '1 Cabramatta','1960-09-01', true, 0,'', 'M'), " +
" ('Jimmy 2','Tran', 'Ho.Tran@hotmail.com', '003', '34 Cabramatta','1980-09-01', true, 1,'','M'), " +
" ('Joe 3','Tran', 'Joe.Tran@hotmail.com', '006', '32 Cabramatta','1980-10-01', true, 1,'','M'), " +
" ('John 4','Tran', 'John.Tran@hotmail.com', '008', '30 Cabramatta','1990-12-01', true, 3,'','M')," +
" ('Lee 5','Tran', 'Lee.Tran@hotmail.com', '030', '18 Cabramatta','2000-12-01', true, 2,'','M'), " +
" ('Len 6','Nguyen', 'Len.nguyen@hotmail.com', '001', '1 Home','1950-01-01', true, 0,'','M'), " +
" ('Son 7','Nguyen', 'son.Nguyen@hotmail.com', '001', '10 Home','1980-01-01', true,6,'','M'), " +
" ('Loa 8','Tran', 'Loa.Tran@hotmail.com', '020', '11 Cabramatta','2002-12-01', true, 3,'','M'), " +
" ('Du 9','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 4,'','M'), " +
" ('Linh 10','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 5,'','M'), " +
" ('COA 11','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 8,'','M'), " +
" ('Hoa 12','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 8,'','F'), " +
" ('Nhi 13','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 8,'','F'), " +
" ('Mai 14','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 8,'','F'), " +
" ('Trang 15','Tran', 'Du.Tran@hotmail.com', '001', '12 Cabramatta','2002-12-01', true, 7,'','F'), " +
" ('Tom 16','Tran', 'Ho.Tran@hotmail.com', '007', '34 Cabramatta','1999-01-01', true, 2,'','M');";
try
{
int count = _context.staff.Count();
if (count < 1)
{
var conn = _context.Database.GetDbConnection();
try
{
conn.Open();
var command = conn.CreateCommand();
command.CommandText = txt;
command.CommandType = System.Data.CommandType.Text;
command.ExecuteNonQuery();
command.CommandText = workertxt;
command.CommandType = System.Data.CommandType.Text;
command.ExecuteNonQuery();
id = 9;
}
catch
{
id = -1;
}
finally
{
conn.Close();
}
}
else
id = 1;
}
catch
{
id = -10;
}
return id;
}
}
@@ -0,0 +1,381 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FamilyTreeAPI.Models;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Interface;
using DocumentFormat.OpenXml.Drawing.Diagrams;
using Microsoft.AspNetCore.Http;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
namespace FamilyTreeAPI.Repository;
/* password = cGFzc3dvcmQ=
*
INSERT INTO public.staff(
firstname, lastname, email, phone, stype, srole, spassword, sactive)
VALUES ( 'kham', 'vilaythong', 'kham.vilaythong', '009', 1, 2, 'cGFzc3dvcmQ=', true);
*/
public class StaffRepository : IStaff
{
private readonly FamilyTreeDBContext _context;
private readonly IHttpContextAccessor _httpContext;
public StaffRepository(FamilyTreeDBContext context, IHttpContextAccessor httpContext)
{
_context = context;
_httpContext = httpContext;
}
private StaffDto FillDto(staff model)
{
StaffDto dto = new StaffDto();
dto.Firstname = model.Firstname;
dto.Lastname = model.Lastname;
dto.Type = model.Stype;
dto.Phone = model.Phone;
dto.Active = model.Sactive ?? false;
dto.Email = model.Email;
/*
dto.AddedOn = model.AddedOn;
dto.RoleType = model.RoleType;
*/
dto.RoleType = model.Srole;
dto.Id = model.Id;
return dto;
}
private staff FillModel(staff model, StaffDto dto)
{
if (!string.IsNullOrEmpty(dto.Firstname))
model.Firstname = dto.Firstname.Trim();
if (!string.IsNullOrEmpty(dto.Lastname))
model.Lastname = dto.Lastname.Trim();
if (!string.IsNullOrEmpty(dto.Phone))
model.Phone = dto.Phone.Trim();
if (dto.Id > 0)
model.Id = dto.Id;
if (!string.IsNullOrEmpty(dto.Password))
{
string password = dto.Password.Trim();
model.Spassword = Ultils.Base64Encode(password);
}
model.Email = dto.Email;
model.Srole = dto.RoleType;
model.Sactive = dto.Active;
return model;
}
public async Task<ResultModel<Dictionary<int,StaffDto>>> GetDicStaffs()
{
Dictionary<int,StaffDto> dlist = new();
int statuscode = 0;
string error = "";
StaffDto item;
staff model;
try
{
var list = await _context.staff.ToListAsync();
for (int i = 0; i< list.Count; i++)
{
model = list[i];
item = FillDto(model);
dlist.Add(item.Id, item);
}
statuscode = 1;
//list.Sort((x, y) => x.Code.CompareTo(y.Code));
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<Dictionary<int,StaffDto>>()
{
Data = dlist,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<List<StaffDto> >> GetStaff(StaffCriteria criteria)
{
List<StaffDto> list = new();
int statuscode = 0;
string error = "";
try
{
list = await _context.LoadStaffAsync(criteria);
statuscode = 1;
//list.Sort((x, y) => x.Code.CompareTo(y.Code));
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<List<StaffDto>>()
{
Data = list,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<StaffDto>> GetStaffById(int id)
{
int statuscode = 0;
string error = "";
StaffDto dto = new StaffDto();
try
{
var item = await _context.staff.FindAsync(id);
if (item == null)
{
statuscode = -1;
}
else
{
dto = FillDto(item);
statuscode = 1;
}
}
catch(Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<StaffDto>()
{
Data = dto,
StatusCode = statuscode,
Message = error
};
}
private string GetDateTimeNow()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
public async Task<ResultModel<int>> ResetPassword(ResetPassDto item)
{
int result = -1;
int statuscode = 0;
string error = "";
try
{
staff? model1 = await _context.staff.FindAsync(item.Id);
if (model1 != null)
{
if (!string.IsNullOrEmpty(item.Password))
{
string password = item.Password.Trim();
model1.Spassword = Ultils.Base64Encode(password);
}
// model.LastModified = DateTime.Now;
// model.LastModifiedId = loginName;
var successid = await _context.SaveChangesAsync();
result = item.Id;
}
statuscode = 1;
}
catch (Exception ex)
{
statuscode = -1;
error = ex.ToString();
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> SaveStaff(StaffDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
HttpContext? httpContext = _httpContext.HttpContext;
string loginName = "";
if (httpContext != null)
{
UserDto? user = (UserDto?)httpContext.Items["User"];
if (user != null)
loginName = user.FirstName + " " + user.LastName;
}
try
{
if (item.Id < 1)
{
bool already = await CheckLoginAlready(item.Email.Trim());
if (already)
{
return new ResultModel<int>()
{
Data = 0,
StatusCode = 0,
Message = "user name already exist in Database"
};
}
}
staff model;
if (item.Id < 1)
{
model = new();
model = FillModel(model, item);
// model.Active = true;
// model.AddedBy = loginName;
// model.AddedOn = DateTime.Now;
_context.staff.Add(model);
await _context.SaveChangesAsync();
result = model.Id;
}
else
{
staff? model1 = await _context.staff.FindAsync(item.Id);
model1 = FillModel(model1, item);
// model.LastModified = DateTime.Now;
// model.LastModifiedId = loginName;
var successid = await _context.SaveChangesAsync();
result = item.Id;
}
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
private async Task<bool> CheckLoginAlready(string login)
{
bool result = false;
var model = await _context.staff.Where(x => x.Email == login).ToListAsync();
if (model.Count > 0)
result = true;
return result;
}
public async Task<ResultModel<int>> SaveStaffNew(StaffDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
try
{
if (item.Id < 1)
{
bool already = await CheckLoginAlready(item.Email.Trim());
if (already)
{
return new ResultModel<int>()
{
Data = 0,
StatusCode = 0,
Message = "user name already exist in db"
};
}
}
staff model;
if (item.Id < 1)
{
model = new();
model = FillModel(model, item);
// model.AddedOn = DateTime.Now;
// model.Active = true;
_context.staff.Add(model);
}
else
{
model = await _context.staff.FindAsync(item.Id);
model = FillModel(model, item);
}
var successid = await _context.SaveChangesAsync();
result = 1;
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> Delete(int id)
{
int result = 1;
int statuscode = 0;
string error = "";
try
{
staff model;
model = await _context.staff.FindAsync(id);
// if (model != null)
// model.Active = false;
var successCount = await _context.SaveChangesAsync();
statuscode = 1;
result = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
}
+251
View File
@@ -0,0 +1,251 @@
/**************************************/
CREATE TABLE IF NOT EXISTS public.client
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
clientname character(80) COLLATE pg_catalog."default",
contact character(80) COLLATE pg_catalog."default",
cactive boolean,
address character(120),
email character(80),
phone character(30),
CONSTRAINT client_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.client
OWNER to postgres;
CREATE TABLE IF NOT EXISTS public.lookup
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
code character(10) COLLATE pg_catalog."default",
description character(80) COLLATE pg_catalog."default",
lactive boolean,
ltype character(20) COLLATE pg_catalog."default",
CONSTRAINT lookup_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.lookup
OWNER to postgres;
-- Table: public.job
-- DROP TABLE IF EXISTS public.job;
CREATE TABLE IF NOT EXISTS public.job
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
code character(10) COLLATE pg_catalog."default",
description character(80) COLLATE pg_catalog."default",
jactive boolean,
CONSTRAINT job_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.job
OWNER to postgres;
-- Table: public.servicetask
-- DROP TABLE IF EXISTS public.servicetask;
CREATE TABLE IF NOT EXISTS public.servicetask
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
assignto integer,
clientid integer,
code character(10) COLLATE pg_catalog."default",
description character(80) COLLATE pg_catalog."default",
sdate date,
serviceno character(20) COLLATE pg_catalog."default",
staffid integer,
status integer,
CONSTRAINT servicetask_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.servicetask
OWNER to postgres;
-- Table: public.staffwork
-- DROP TABLE IF EXISTS public.staffwork;
CREATE TABLE IF NOT EXISTS public.staffwork
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
description character(80) COLLATE pg_catalog."default",
sactive boolean,
staffid integer,
startdate date,
CONSTRAINT staffwork_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.staffwork
OWNER to postgres;
-- Table: public.staffworkdetail
-- DROP TABLE IF EXISTS public.staffworkdetail;
CREATE TABLE IF NOT EXISTS public.staffworkdetail
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
jobid integer,
sactive boolean,
starttime timestamp without time zone,
stoptime timestamp without time zone,
task character(80) COLLATE pg_catalog."default",
swid integer,
CONSTRAINT staffworkdetail_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.staffworkdetail
OWNER to postgres;
/******************************************/
ALTER TABLE servicetask
ADD FOREIGN KEY (clientid) REFERENCES client(id);
ALTER TABLE servicetask
ADD FOREIGN KEY (staffid) REFERENCES staff(id);
ALTER TABLE servicetask
ADD FOREIGN KEY (assignto) REFERENCES staff(id);
ALTER TABLE staffwork
ADD FOREIGN KEY (staffid) REFERENCES staff(id);
ALTER TABLE staffworkdetail
ADD FOREIGN KEY (swid) REFERENCES staffwork(id);
ALTER TABLE staffworkdetail
ADD FOREIGN KEY (jobid) REFERENCES job(id);
/************************************/
CREATE OR REPLACE FUNCTION usp_search_user (
iemail character varying,
ifirstname character varying,
ilastname character varying)
RETURNS TABLE(id integer, fistname character varying, lastname character varying, email character varying, stype integer, sactive boolean, srole integer, spassword character varying)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
begin
return query SELECT
e.id,
e.firstname,
e.lastname,
e.email,
e.stype,
e.sactive,
e.srole,
e.spassword
FROM staff e
WHERE (iemail = '' or e.email ilike iemail || '%')
and (ilastname = '' or e.lastname ilike ilastname || '%')
and (ifirstname = '' or e.firstname ilike ifirstname || '%');
end;
$BODY$;
CREATE OR REPLACE FUNCTION usp_staffwork_detail(
ifromdate date,
itodate date,
istaffid integer)
RETURNS TABLE(id integer, staffid integer, description character varying(80),
startdate date, sactive boolean, did integer, starttime timestamp, stoptime timestamp,
task character varying(80))
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
begin
return query SELECT
w.id,
w.staffid,
w.description,
w.startdate,
w.sactive,
d.id as did,
d.starttime,
d.stoptime,
d.task
FROM staffwork w,
staffworkdetail d
where w.id = d.swid
and (istaffid = 0 or w.staffid = istaffid)
and w.startdate >= ifromdate
and w.startdate <= itodate
order by id, did;
end;
$BODY$;
CREATE OR REPLACE FUNCTION usp_servicetask_sel(
ifromdate date,
itodate date,
istaffid integer,
iassignto integer,
iclientid integer
)
RETURNS TABLE(id integer,
staffid integer,
sdate date,
description character varying(80),
code character varying(10),
status integer,
assignTo integer,
clientid integer,
serviceno character varying(20))
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
begin
return query SELECT
s.id,
s.staffid,
s.sdate,
s.description,
s.code,
s.status,
s.assignto,
s.clientid,
s."serviceNo"
FROM servicetask s
where (istaffid < 1 or s.staffid = istaffid)
and (iassignto < 1 or s.assignto = iassignto)
and (iclientid < 1 or s.clientid = iclientid)
and s.sdate >= ifromdate
and s.sdate <= itodate
;
end;
$BODY$;
+16
View File
@@ -0,0 +1,16 @@
namespace FamilyTreeAPI.Repository
{
public class Ultils
{
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
}
}
@@ -0,0 +1,257 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Entities;
using System;
using FamilyTreeAPI.Models;
using Microsoft.AspNetCore.Http;
using System.Text.Json;
namespace FamilyTreeAPI.Repository;
public class UserServiceRepository : IUserService
{
private FamilyTreeDBContext _context;
private IJwtUtils _jwtUtils;
private readonly IHttpContextAccessor _httpcontext;
private readonly AppSettings _appSettings;
public UserServiceRepository(
FamilyTreeDBContext context,
IJwtUtils jwtUtils,
IHttpContextAccessor httpcontext,
IOptions<AppSettings> appSettings)
{
_context = context;
_jwtUtils = jwtUtils;
_appSettings = appSettings.Value;
this._httpcontext = httpcontext;
}
public Task<ResultModel<int>> Logout(string token, UserDto user, string remoteIpAddress)
{
/*
int retval = 1;
int statuscode = 1;
string str255 = token;
var histo = await _context.AdminLoginHistories.Where(x => x.UserId == user.Id
&& x.RecordIntegrity == token
&& x.LoginTyped == user.Username).ToListAsync();
if (histo.Count > 0)
{
histo[0].LogoutDatetime = DateTime.Now;
await _context.SaveChangesAsync();
}
*/
var result = new ResultModel<int>()
{
Data = 1,
StatusCode = 1
};
return Task.FromResult(result);
}
private bool checkLogin(staff user, string email, string password)
{
bool result = false;
// string dpassword = Ultils.Base64Encode(password);
result = user.Spassword == password;
return result;
}
public async Task<ResultModel<AuthenticateResponse>> Login(AuthenticateRequest model)
{
UserDto myUser = new();
AuthenticateResponse retval = null;
string error = "user name is not in DB or user Name profile is not generic";
int statuscode = 0;
try
{
//now check the adminuser table
myUser.Username = model.Username;
var user = _context.staff.
SingleOrDefault(x => x.Email == model.Username
&& true == x.Sactive);
if (user != null)
{
bool loginOK = checkLogin(user, model.Username, model.Password);
if (loginOK)
{
// myUser.Role = user.RoleType;
myUser.Id = user.Id;
myUser.Role = user.Srole ?? 0;
myUser.Email = user.Email;
myUser.Phone = user.Phone;
myUser.FirstName = user.Firstname;
myUser.LastName = user.Lastname;
//myUser.ValidationPointId = user.ValidationPointID ?? 0;
statuscode = 1;
}
else //not allow
{
statuscode = -1;
myUser.Role = 1;
myUser.Id = -1;
error = "user name cannot login email or password";
}
// validate
// if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
// authentication successful so generate jwt token
if (statuscode == 1)
{
var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
retval = new AuthenticateResponse(myUser, jwtToken, myUser.Role);
error = "";
}
}
else
{
error = "user name or password is not correct";
}
}
catch (Exception ex)
{
retval = null;
error = ex.ToString();
statuscode = -1;
}
//writelog for login user.
// if (myUser != null)
// await AddToSession(myUser);
return new ResultModel<AuthenticateResponse>()
{
Data = retval,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<AuthenticateResponse>> LoginApiAD(AuthenticateRequest model, string remoteIpAddress)
{
UserDto myUser = new();
AuthenticateResponse retval = null;
string error = "user name is not in DB or user Name profile is not generic";
int statuscode = 0;
string webAPIUrl = _appSettings.LoginWebAPI;
//KCO, D204KCO
//now check the adminuser table
//ward clerk
try
{
//now check the adminuser table
myUser.Username = model.Username;
var user = _context.staff.
SingleOrDefault(x => x.Email == model.Username
&& true == x.Sactive);
if (user != null)
{
bool loginOK = checkLogin(user,model.Username, model.Password);
if (loginOK)
{
// myUser.Role = user.RoleType;
myUser.Id = user.Id;
myUser.Role = user.Srole ?? 0;
myUser.Email = user.Email;
myUser.Phone = user.Phone;
myUser.FirstName = user.Firstname;
myUser.LastName = user.Lastname;
//myUser.ValidationPointId = user.ValidationPointID ?? 0;
statuscode = 1;
}
else // allow
{
statuscode = 1;
myUser.Role = 1;
myUser.Id = -1;
//error = "user name does not exist in adminUser";
}
// validate
// if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
// authentication successful so generate jwt token
if (statuscode == 1)
{
var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
retval = new AuthenticateResponse(myUser, jwtToken, myUser.Role);
error = "";
}
}
else
{
error = "user name or password is not correct";
}
}
catch (Exception ex)
{
retval = null;
error = ex.ToString();
statuscode = -1;
}
//writelog for login user.
// if (myUser != null)
// await AddToSession(myUser);
return new ResultModel<AuthenticateResponse>()
{
Data = retval,
StatusCode = statuscode,
Message = error
};
}
//get like this
private async Task GetCurrentUser()
{
await _httpcontext.HttpContext.Session.LoadAsync();
string userString = _httpcontext.HttpContext.Session.GetString("user");
if (userString != null && userString != "")
{
var user = JsonSerializer.Deserialize<UserDto>(userString);
if (user != null)
{
// return user;
}
}
}
/*
private User LoginADStaff(ADConfig adConfig, string username, string password)
{
ADStaffLink staffLink = new ADStaffLink(adConfig);
MyADObject myADObj = staffLink.CheckADCredentials(username,password);
User user = new()
{
Username = myADObj.StafflinkNo,
Email = myADObj.Email,
FirstName = myADObj.FirstName,
LastName = myADObj.LastName
};
// myADObj.JobTitle;
return user;
// return null;
}
*/
}
@@ -0,0 +1,118 @@
/*
declare @id int
set @id = 7
delete from MotorAccess where mv_id = @id
delete from [dbo].[MotorVehicle]
where mv_id = @id
*/
CREATE OR REPLACE FUNCTION public.usp_search_user(
iemail character varying,
ifirstname character varying,
ilastname character varying)
RETURNS TABLE(id integer, fistname character varying, lastname character varying, email character varying, stype integer, sactive boolean, srole integer, spassword character varying)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
begin
return query SELECT
e.id,
e.firstname,
e.lastname,
e.email,
e.stype,
e.sactive,
e.srole,
e.spassword
FROM staff e
WHERE (iemail = '' or e.email ilike iemail || '%')
and (ilastname = '' or e.lastname ilike ilastname || '%')
and (ifirstname = '' or e.firstname ilike ifirstname || '%');
end;
$BODY$;
CREATE OR REPLACE FUNCTION get_staff (
iemail character varying,
ifirstname character varying,
ilastname character varying
)
RETURNS TABLE (
id int,
firstname varchar,
lastname varchar,
email varchar,
stype INT,
sactive boolean,
srole INT,
spassword varchar )
AS $$
BEGIN
RETURN QUERY
e.id,
e.firstname,
e.lastname,
e.email,
e.stype,
e.sactive,
e.srole,
e.spassword
FROM staff e
WHERE (iemail = '' or e.email ilike iemail || '%')
and (ilastname = '' or e.lastname ilike ilastname || '%')
and (ifirstname = '' or e.firstname ilike ifirstname || '%');
END; $$
LANGUAGE 'plpgsql';
how to host under .net 8 web api under linux
1) create [webAPI_name].service
******************************************
# Example: /etc/systemd/system/yourwebapp.service
[Unit]
Description=Your .NET 8 Web API
After=network.target
[Service]
WorkingDirectory=/var/www/yourwebapp
ExecStart=/usr/bin/dotnet /var/www/yourwebapp/YourWebApi.dll
Restart=always
RestartSec=10
SyslogIdentifier=yourwebapp
User=www-data # or a dedicated user
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
************************************************
2) start /stop the service under linux
***********************************************
sudo systemctl enable yourwebapp.service
sudo systemctl start yourwebapp.service
**********************************************
3) host under nginx or apache
************************************************
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:5000; # Kestrel's listening port
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
***********************************************************************
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"AppSettings": {
"Secret": "Nepean Blue Mountain Super Secret SIGN AND VERIFY JWT TOKENS, BEARER TOKEN USE WHEN CALLING THIS API.",
"SQLConnectionString": "host=localhost;port=5432;database=FamilyTreeDB;username=postgres;password=Positive~1;",
"LoginWebAPI": "http://nephmdb-sql006/CommonWebApiAD/api/AD",
"ClientURL": "http://localhost:4200/approval",
"ImageFolder": "c:\\temp\\Family"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.DataProtection": "None"
}
},
"AllowedHosts": "*"
}