update TWA Management v0.0.1

This commit is contained in:
2025-11-05 10:08:06 +07:00
parent d4e91c7960
commit b4b191f829
73 changed files with 2249 additions and 418 deletions

View File

@ -0,0 +1,17 @@
using AppLibs.Libs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace TWASys_App.Controllers
{
[AllowAnonymous]
public class LoginController : Controller
{
[Layout(LayoutOptions.Custom, "Login")]
[PageInfor("10001", "Login")]
public async Task<IActionResult> Index()
{
return await this.ViewAsync();
}
}
}

View File

@ -1,13 +1,9 @@
using AppLibs.Libs;
using TWASys_App.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Connections.Features;
using System.Diagnostics.Metrics;
using System.Security.Cryptography;
using System.Text.Encodings;
using System.Text;
using AppLibs.Libs.Crypt;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using System.Security.Cryptography;
using TWASys_App.Models;
using TWASys_App.Models.ServerInfo;
namespace TWASys_App.Controllers
@ -83,36 +79,40 @@ namespace TWASys_App.Controllers
return Json(await model.UpdateAsync());
}
[HttpPost]
public async Task<IActionResult> SetStorageData([FromForm] StorageModel model)
{
return Json(await model.AddAsync());
}
[HttpGet]
public async Task<IActionResult> GenerationAccessToken()
{
var t1 = Task<string>.Run(() =>
var t1 = Task<Guid>.Run(() =>
{
var g = Guid.NewGuid();
return Base64UrlTextEncoder.Encode(g.ToByteArray().Concat(BitConverter.GetBytes(DateTime.UtcNow.ToFileTime())).ToArray());
return UUID7.NewUuid7();
});
var t2 = Task<string>.Run(() => {
var g = Guid.NewGuid();
var bytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
var tokenValue = Base64UrlTextEncoder.Encode(
Guid.NewGuid().ToByteArray()
.Concat(BitConverter.GetBytes(DateTime.UtcNow.ToFileTimeUtc()))
.ToArray()
);
using var sha = SHA256.Create();
var idToken = WebEncoders.Base64UrlEncode(sha.ComputeHash(
System.Text.Encoding.UTF8.GetBytes(tokenValue)
));
Array.Resize(ref bytes, 16);
byte[] data = new byte[32];
bytes.CopyTo(data, 0);
g.ToByteArray().CopyTo(data, 16);
var hash = new CRC64();
return hash.HashToString(data);
return idToken;
});
await Task.WhenAll(t1, t2);
return Json(new
{
idToken = t2.Result.ToLower(),
tokenValue = t1.Result
idToken = t1.Result.ToString(),
tokenValue = t2.Result.ToLower()
});
}

View File

@ -4,7 +4,7 @@ namespace TWASys_App.DBModels
{
public class DBManagement
{
public static string GetConnectionString()
public static string GetConnectionString(bool allowVar = false)
{
string fp = Path.GetFullPath("Keys/db/");
@ -28,6 +28,7 @@ namespace TWASys_App.DBModels
SslCa = Path.Combine(fp, "ca-cert.pem"),
SslCert = Path.Combine(fp, "client-cert.pem"),
SslKey = Path.Combine(fp, "client-key.pem"),
AllowUserVariables = allowVar
};
//172.168.192.204
return builder.ConnectionString;

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class Files
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public ulong IdFiles { get; set; }
[ForeignKey("IdFolders")]
public ulong IdFolders { get; set; } // BIGINT FK → Folders.idFolders
public string Code { get; set; } = ""; // VARCHAR(100)
public string Name { get; set; } = ""; // VARCHAR(100)
public string Path { get; set; } = ""; // TEXT
public string Options { get; set; } = ""; // LONGTEXT (JSON, metadata)
public DateTime CreateDate { get; set; } = DateTime.UtcNow; // DATETIME (UTC khuyên dùng)
public DateTime? LastModified { get; set; } = null; // DATETIME NULL
public int Status { get; set; } // INT(11)
public Folder? Folder { get; set; } = null!; // nav
}
}

View File

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class Folder
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public ulong IdFolders { get; set; } // BIGINT PK
public ulong? IdParent { get; set; } // BIGINT FK, null = root
public string Name { get; set; } = ""; // VARCHAR(45)
public string Code { get; set; } = ""; // VARCHAR(100)
public string Path { get; set; } = ""; // TEXT
public string Options { get; set; } = ""; // LONGTEXT
public DateTime CreateDate { get; set; } = DateTime.UtcNow; // DATETIME
public DateTime? LastModified { get; set; } = null; // DATETIME NULL
public int Status { get; set; } // INT(11)
public Folder? Parent { get; set; } = null;
public ICollection<Folder> Children { get; set; } = new List<Folder>();
}
}

View File

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class Folders_has_StorageArea
{
[ForeignKey("")]
public ulong IdFolders { get; set; }
[ForeignKey("")]
public long IdStorage { get; set; }
public Folder Folder { get; set; } = null!;
public StorageArea Storage { get; set; } = null!;
}
}

View File

@ -7,66 +7,30 @@ namespace TWASys_App.DBModels
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("idLocalServer")]
public int IdLocalServer { get; set; } = 0;
public long IdLocalServer { get; set; } = 0;
[StringLength(20)]
[Column("ipPrivateServer")]
public string IpPrivateServer { get; set; } = "";
[StringLength(100)]
[Column("ipPrivateServer6")]
public string IpPrivateServer6 { get; set; } = "";
[StringLength(100)]
[Column("ipPublicServer")]
public string IpPrivateServerv6 { get; set; } = "";
public string IpPublicServer { get; set; } = "";
[StringLength(45)]
[Column("pathServer")]
public string PathServer { get; set; } = "";
[StringLength(100)]
[Column("serialNumber")]
public string SerialNumber { get; set; } = "";
// Ảnh gốc ghi "osVesion" (sai chính tả). Giữ nguyên để khớp DB.
[StringLength(100)]
[Column("osVesion")]
public string OsVersion { get; set; } = "";
[StringLength(100)]
[Column("osName")]
public string OsName { get; set; } = "";
[StringLength(45)]
[Column("osArch")]
public string OsArch { get; set; } = "";
// Ảnh gốc ghi "osKernal". Giữ nguyên để khớp DB.
[StringLength(100)]
[Column("osKernal")]
public string OsKernel { get; set; } = "";
[Column("socketNum")]
public string OsKernal { get; set; } = "";
public int SocketNum { get; set; } = 0;
[StringLength(150)]
[Column("cpuName")]
public string CpuName { get; set; } = "";
public float TotalRam { get; set; } = 0;
[Column("totalRam")]
public int TotalRam { get; set; } = 0;
[StringLength(100)]
[Column("biosVendor")]
public string BiosVendor { get; set; } = "";
[StringLength(100)]
[Column("productUUID")]
public string BiosVender { get; set; } = "";
public string ProductUuid { get; set; } = "";
[Column("status")]
public int Status { get; set; } = 0;
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class MicrosoftAccount
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IdCloudAccount { get; set; }
public string AccName { get; set; } = null!;
public string ClientID { get; set; } = null!; // GUID string
public string TenantID { get; set; } = null!;
public string? ClientSecret { get; set; } // encrypted at rest
public string? SiteID { get; set; }
public string? DriveID { get; set; }
public string? PathSharePoint { get; set; }
public string? RefreshToken { get; set; } // encrypted
public string? AccessToken { get; set; } // optional cache
public DateTime? ExpiresAt { get; set; }
public string? Scopes { get; set; }
public DateTime CreateDate { get; set; }
public DateTime? LastModified { get; set; }
public int Status { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class RefreshToken
{
[Key]
public string IdRefreshToken { get; set; } = "";
[ForeignKey("IdServerAuthorization")]
public ulong IdServerAuthorization { get; set; }
public string __RefreshToken { get; set; } = ""; // refreshToken
public DateTime CreateDate { get; set; }
public DateTime ExpireDate { get; set; }
public int Status { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class RefreshToken_Log
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public ulong IdRefreshTokenLog { get; set; }
public string IdRefreshToken { get; set; } = null!;
public DateTime DateRenew { get; set; } // UTC
public int Count { get; set; } = 1;
public int LifeTime { get; set; }
public int Status { get; set; } = 1;
public RefreshToken RefreshToken { get; set; } = null!;
}
}

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class ServerAuthorization
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public ulong IdServerAuthorization { get; set; }
[ForeignKey("IdStorageServer")]
public long IdStorageServer { get; set; }
public DateTime CreateDate { get; set; }
public int Count { get; set; }
public int Status { get; set; }
[NotMapped()]
public ICollection<ServerAuthorization_has_Token> Tokens { get; set; } = new List<ServerAuthorization_has_Token>();
}
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class ServerAuthorization_has_Token
{
[ForeignKey("")]
public ulong IdServerAuthorization { get; set; }
[ForeignKey("")]
public string IdToken { get; set; } = "";
public int Count { get; set; }
public int Status { get; set; }
public ServerAuthorization ServerAuthorization { get; set; } = null!;
public Token Token { get; set; } = null!;
}
}

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class StorageArea
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IdStorage { get; set; } // PK (AUTO_INCREMENT nếu DB đang để vậy)
public ulong? IdEmp { get; set; } = null; // FK -> Emp (nếu có)
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
public double TotalSize { get; set; } = 0; // map FLOAT MySQL -> double
public int Status { get; set; } = 0;
}
}

View File

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class StorageArea_has_StorageServer
{
[ForeignKey("IdStorage")]
public long IdStorage { get; set; }
[ForeignKey("IdStorageServer")]
public long IdStorageServer { get; set; }
[Column("priority", TypeName = "int")]
public int Priority { get; set; } = 0;
[Column("createDate", TypeName = "datetime")]
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
[Column("status", TypeName = "int")]
public int Status { get; set; } = 0;
}
}

View File

@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class StorageServer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IdStorageServer { get; set; }
public long? IdEmp { get; set; }
[ForeignKey("IdTypeStorageServer")]
public long IdTypeStorageServer { get; set; }
public string StorageName { get; set; } = "";
public DateTime? CreateDate { get; set; }
public string ControllerID { get; set; } = "";
public int Status { get; set; } = 0;
}
}

View File

@ -2,22 +2,22 @@
namespace TWASys_App.DBModels
{
public class StorageServerHasLocalServer
public class StorageServer_has_LocalServer
{
[Column("idStorageServer")]
public int IdStorageServer { get; set; } = 0;
[Column("idLocalServer")]
public int IdLocalServer { get; set; } = 0;
[ForeignKey("IdStorageServer")]
public long IdStorageServer { get; set; } = 0;
[Column("createDate")]
[ForeignKey("IdLocalServer")]
public long IdLocalServer { get; set; } = 0;
public DateTime CreateDate { get; set; } = DateTime.UtcNow; // nên lưu UTC
[Column("modifyDate")]
public DateTime? ModifyDate { get; set; } = null; // nên lưu UTC
[Column("status")]
public int Status { get; set; } = 0;
}
}

View File

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class StorageServer_has_MicrosoftAccount
{
[ForeignKey("")]
public long IdStorageServer { get; set; }
[ForeignKey("")]
public long IdCloudAccount { get; set; }
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
public int Status { get; set; } = 1;
public StorageServer StorageServer { get; set; } = null!;
public MicrosoftAccount CloudAccount { get; set; } = null!;
}
}

View File

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class StorageServers_ValidationDomain
{
[ForeignKey("")]
public long IdStorageServer { get; set; }
[ForeignKey("")]
public long IdValidationDomain { get; set; }
[Column("modifyDate", TypeName = "datetime")]
public DateTime? ModifyDate { get; set; } = null;
[Column("createDate", TypeName = "datetime")]
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
[Column("status", TypeName = "int")]
public int Status { get; set; } = 0;
}
}

View File

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class SyncFile_Log
{
public ulong Id { get; set; }
[ForeignKey("")]
public long IdFiles { get; set; }
[ForeignKey("")]
public long IdStorageServer { get; set; }
[ForeignKey("")]
public long IdLocalServer { get; set; }
[ForeignKey("")]
public long IdCloudAccount { get; set; } // FK -> CloudAccounts.id
public DateTime SyncDate { get; set; } = DateTime.UtcNow; // UTC
public string? PathOnServer { get; set; } // đường dẫn lưu trên đích
public int Status { get; set; } // 0=pending,1=ok,2=retry,3=failed,...
// nav
public Files File { get; set; } = null!;
}
}

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class Token
{
[Key]
public string IdToken { get; set; } = "";
public string AccessToken { get; set; } = "";
public DateTime CreateDate { get; set; }
public DateTime ExpireDate { get; set; }
public int Status { get; set; }
}
}

View File

@ -1,10 +1,12 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class TypeStorageServer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int IdTypeStorageServer { get; set; }
public string TypeName { get; set; }

View File

@ -1,11 +1,13 @@
using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TWASys_App.DBModels
{
public class ValidationDomain
{
[Key]
public int IdValidationDomain { set; get; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IdValidationDomain { set; get; }
public string Protocol { set; get; }
public int PortNumber { set; get; }

View File

@ -0,0 +1,329 @@
using Dapper;
using Microsoft.AspNetCore.Identity;
using MySqlConnector;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Globalization;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Intrinsics.Arm;
using System.Text;
namespace TWASys_App.Dapper.AExtentions
{
public class DataValue
{
public object? Data { set; get; }
public string Name { set; get; } = "";
public string PKName { set; get; } = "";
}
public class BatchInsert
{
private IDbConnection _connect;
private IDbTransaction _transaction;
private Dictionary<string, DataValue> _dataKey;
private List<DataValue> _list;
private StringBuilder queryBatch = new();
public int IdTable = 100;
public BatchInsert(IDbConnection connect, IDbTransaction transaction)
{
_connect = connect;
_transaction = transaction;
_dataKey = new Dictionary<string, DataValue>();
_list = new List<DataValue>();
}
public void AddRow<T>(T obj)
{
var dt = new DataValue
{
Name = "",
PKName = "",
Data = obj
};
_list.Add(dt);
var p = DapperCommand.QueryInsert(obj, _dataKey, IdTable);
IdTable++;
dt.Name = p.Name;
dt.PKName = p.KeyVar;
if (p.IsKeyAI)
{
_dataKey.TryAdd(p.KeyVar, dt);
}
queryBatch.AppendLine(p.Query);
}
public string GetQuery()
{
string query = string.Empty;
foreach (var (key, value) in _dataKey)
{
query += $"Select @tb{value.Name}_{key} As {key}; \n";
}
queryBatch.AppendLine(query);
return queryBatch.ToString();
}
public async Task ExcuteQuery()
{
var dynamic = ToDynamicParametersSeqPrefix(_list);
var str = GetQuery();
Console.WriteLine(str);
using var grid = await _connect.QueryMultipleAsync(str, dynamic, _transaction);
await MapAutoIncrementIdsAsync(grid, _dataKey.Values);
}
public static async Task MapAutoIncrementIdsAsync(SqlMapper.GridReader grid,IEnumerable<DataValue> items)
{
foreach (var dv in items)
{
var obj = dv?.Data;
if (obj is null) continue;
var (pk, isAuto) = FindPrimaryKey(obj.GetType());
if (pk is null || !isAuto) continue; // không phải auto-inc → không đọc scalar
// nếu object đã có ID (không rỗng) thì bỏ qua để không lệch thứ tự result set
var cur = pk.GetValue(obj);
if (!IsEmptyId(cur)) continue;
// đọc scalar từ SELECT kế tiếp và gán lại cho property khóa
var raw = await grid.ReadSingleAsync<object>();
var targetType = Nullable.GetUnderlyingType(pk.PropertyType) ?? pk.PropertyType;
if (raw is IDictionary<string, object> row)
{
if (!row.TryGetValue(dv?.PKName, out raw))
throw new InvalidOperationException($"Missing column {dv?.PKName}");
}
// MySqlDecimal → decimal
if (raw?.GetType().FullName == "MySql.Data.Types.MySqlDecimal")
{
var t = raw.GetType();
raw = (decimal)t.GetProperty("Value")!.GetValue(raw)!;
}
// Giờ o phải là số: long/ulong/int/decimal/…
var target = Nullable.GetUnderlyingType(pk.PropertyType) ?? pk.PropertyType;
pk.SetValue(obj, ConvertNumericTo(target, raw));
}
}
static object ConvertNumericTo(Type target, object? x)
{
// ưu tiên xử lý 2 nhánh chính
if (target == typeof(ulong) || target == typeof(uint) || target == typeof(ushort) || target == typeof(byte))
{
ulong u = x switch
{
ulong v => v,
long v => v < 0 ? throw new OverflowException() : (ulong)v,
int v => v < 0 ? throw new OverflowException() : (ulong)v,
decimal v => v < 0 ? throw new OverflowException() : checked((ulong)v),
_ => Convert.ToUInt64(x, System.Globalization.CultureInfo.InvariantCulture)
};
return target == typeof(ulong) ? u :
target == typeof(uint) ? checked((uint)u) :
target == typeof(ushort) ? checked((ushort)u) :
checked((byte)u);
}
else
{
long s = x switch
{
long v => v,
ulong v => v > (ulong)long.MaxValue ? throw new OverflowException() : (long)v,
int v => v,
decimal v => checked((long)v),
_ => Convert.ToInt64(x, System.Globalization.CultureInfo.InvariantCulture)
};
return target == typeof(long) ? s :
target == typeof(int) ? checked((int)s) :
target == typeof(short) ? checked((short)s) :
checked((sbyte)s);
}
}
public static DynamicParameters ToDynamicParametersSeqPrefix(
IEnumerable<DataValue> inputs // 0 coi là "trống" (trừ property tên Status)
)
{
var dp = new DynamicParameters();
var seen = new HashSet<string>(StringComparer.Ordinal);
foreach (var src in inputs)
{
var t = src.Data?.GetType();
var props = t?.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in props)
{
if (!p.CanRead) continue;
if (IsNotMapped(p)) continue;
if (IsKeyOrForeignKey(p, src.Data))
continue;
var paramName = "tb" + src.Name + "_" + p.Name;
var val = p.GetValue(src.Data);
dp.Add("@" + paramName, val);
}
}
return dp;
}
private static (PropertyInfo? Key, bool IsAutoInc) FindPrimaryKey(Type t)
{
PropertyInfo? key = null; bool auto = false;
foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (HasAttr(p, "System.ComponentModel.DataAnnotations.KeyAttribute", "KeyAttribute",
"Dapper.Contrib.Extensions.KeyAttribute"))
{ key = p; auto = IsDatabaseGeneratedIdentity(p); break; }
if (HasAttr(p, "Dapper.Contrib.Extensions.ExplicitKeyAttribute", "ExplicitKeyAttribute"))
{ key = p; auto = false; break; }
}
// fallback theo tên "Id" nếu không có attribute
key ??= t.GetProperty("Id", BindingFlags.Public | BindingFlags.Instance);
// nếu không tìm được attribute, đoán auto-inc cho kiểu số
if (key != null && !auto)
{
var k = Nullable.GetUnderlyingType(key.PropertyType) ?? key.PropertyType;
auto = k == typeof(int) || k == typeof(long) || k == typeof(uint) || k == typeof(ulong);
}
return (key, auto);
}
private static bool IsDatabaseGeneratedIdentity(PropertyInfo p)
{
// [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
foreach (var ca in p.CustomAttributes)
{
var full = ca.AttributeType.FullName ?? ca.AttributeType.Name;
if (full is "System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute"
or "DatabaseGeneratedAttribute")
{
if (ca.ConstructorArguments.Count == 1 && ca.ConstructorArguments[0].ArgumentType.IsEnum)
return Convert.ToInt32(ca.ConstructorArguments[0].Value) == 1; // Identity = 1
}
}
return false;
}
private static bool IsNotMapped(PropertyInfo p)
{
return HasAttr(p, "System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute", "NotMappedAttribute");
}
private static bool IsKey(PropertyInfo p, object? obj)
{
if( HasAttr(p,
"System.ComponentModel.DataAnnotations.KeyAttribute", "KeyAttribute",
"Dapper.Contrib.Extensions.KeyAttribute"))
{
var val = p.GetValue(obj);
ulong t = 0;
if (val == null && string.IsNullOrWhiteSpace(val?.ToString()))
{
return true;
}
else
{
if (ulong.TryParse(val?.ToString(), out t) && t == 0)
{
return true;
}
}
}
return false;
}
private static bool IsKeyOrForeignKey(PropertyInfo p, object? obj)
{
return IsKey(p, obj) || IsForeignKeyProperty(p, obj);
}
private static bool HasAttr(MemberInfo m, params string[] names)
{
return m.CustomAttributes.Any(ca =>
{
var full = ca.AttributeType.FullName ?? ca.AttributeType.Name;
var shortName = ca.AttributeType.Name;
return names.Contains(full) || names.Contains(shortName);
});
}
private static bool IsForeignKeyProperty(PropertyInfo p, object? obj)
{
// [ForeignKey] ngay trên property
if (HasAttr(p, "System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute", "ForeignKeyAttribute"))
{
var val = p.GetValue(obj);
ulong t = 0;
if (val == null && string.IsNullOrWhiteSpace(val?.ToString()))
{
return true;
}
else
{
if (ulong.TryParse(val?.ToString(), out t) && t == 0)
{
return true;
}
}
}
//// [ForeignKey("PropName")] đặt trên navigation khác, trỏ tới property này
//var my = p.Name;
//foreach (var nav in allProps)
//{
// if (ReferenceEquals(nav, p)) continue;
// var fkAttr = nav.CustomAttributes.FirstOrDefault(ca =>
// (ca.AttributeType.FullName ?? ca.AttributeType.Name) is
// "System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute" or "ForeignKeyAttribute");
// if (fkAttr == default) continue;
// var nameArg = fkAttr.ConstructorArguments.FirstOrDefault().Value?.ToString();
// if (string.IsNullOrWhiteSpace(nameArg))
// nameArg = fkAttr.NamedArguments.FirstOrDefault(a => a.MemberName == "Name").TypedValue.Value?.ToString();
// if (string.IsNullOrWhiteSpace(nameArg)) continue;
// var names = nameArg.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
// .Select(s => s.Trim());
// if (names.Any(n => string.Equals(n, my, StringComparison.OrdinalIgnoreCase)))
// return true;
//}
return false;
}
private static bool IsEmptyId(object? v)
{
if (v is null) return true;
var t = Nullable.GetUnderlyingType(v.GetType()) ?? v.GetType();
if (!t.IsValueType) return false;
try { return v.Equals(Activator.CreateInstance(t)); } catch { return false; }
}
}
public sealed class PropMeta
{
public required PropertyInfo Prop { get; init; }
public required Func<object, object?> Getter { get; init; }
public required Type UnderlyingType { get; init; }
public required bool IsNotMapped { get; init; }
public required bool IsKeyOrForeignKey { get; init; }
}
}

View File

@ -1,12 +1,80 @@
using Dapper;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Data.Common;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Linq;
namespace TWASys_App.Dapper.AExtentions
{
public static class DapperCommand
{
public static async Task Insert<T>(this DbConnection connection, T obj, bool identityInsert = true)
public static dynamic QueryInsert<T>(T obj)
{
return QueryInsert(obj, new Dictionary<string, DataValue>());
}
public static dynamic QueryInsert<T>(T obj, Dictionary<string, DataValue> data, int IdTable = 100)
{
var type = typeof(T);
var tableName = TableMapper.GetTableName(type);
var allProperties = PropertiesCache.TypePropertiesCache(type);
var keyProperties = PropertiesCache.KeyPropertiesCache(type);
var fkProperties = PropertiesCache.FKPropertiesCache(type);
var computedProperties = PropertiesCache.ComputedPropertiesCache(type);
var columns = PropertiesCache.GetColumnNamesCache(type);
var insertProperties = allProperties.Except(computedProperties).Except(fkProperties).ToList();
var insertPropertiesString = string.Empty;
var stringKeyProperty = string.Empty;
var keyAI = string.Empty;
var flag = false;
var q = string.Empty;
if (keyProperties.Count > 0)
{
flag = true;
insertProperties = insertProperties.Except(keyProperties).ToList();
stringKeyProperty = GetColumnsString(keyProperties.ToList(), columns);
keyAI = $@"SET @{GetColumnsString(keyProperties.ToList(), columns, IdTable.ToString(), "")} := LAST_INSERT_ID();";
}
insertPropertiesString = GetColumnsString(insertProperties, columns);
var fkPropertiesString = string.Empty;
var fkValuesString = string.Empty;
if (data.Count > 0)
{
fkPropertiesString = GetColumnsString(fkProperties, columns);
fkValuesString = string.Join(", ", fkProperties.Select(u => {
var ok = data.TryGetValue(u.Name, out var v);
if (ok)
{
return $"@tb{v?.Name}_{u.Name}";
}
else
{
return $"@tb{IdTable}_{u.Name}";
}
}));
fkPropertiesString += (string.IsNullOrEmpty(fkPropertiesString))?"": ", ";
fkValuesString += (string.IsNullOrEmpty(fkValuesString)) ? "" : ", ";
}
q = $@"INSERT INTO {FormatTableName(tableName)} ({fkPropertiesString + insertPropertiesString}) VALUES ({fkValuesString + GetColumnsString(insertProperties, columns, IdTable.ToString(), "@")});
{keyAI}";
return new
{
IsKeyAI = flag,
Query = q,
Name = IdTable.ToString(),
KeyVar = stringKeyProperty
};
}
public static async Task Insert<T>(this DbConnection connection, T obj, IDbTransaction? tx = null)
{
var type = typeof(T);
var tableName = TableMapper.GetTableName(type);
@ -17,13 +85,14 @@ namespace TWASys_App.Dapper.AExtentions
var insertProperties = allProperties.Except(computedProperties).ToList();
var insertPropertiesString = string.Empty;
if (identityInsert)
if (keyProperties.Count > 0)
{
insertProperties = insertProperties.Except(keyProperties).ToList();
insertPropertiesString = GetColumnsString(insertProperties, columns);
var insertedId = await connection.QueryFirstAsync<int>($@"
INSERT INTO {FormatTableName(tableName)} ({insertPropertiesString}) VALUES ({GetColumnsString(insertProperties, columns, "@")});
SELECT LAST_INSERT_ID()", obj);
SELECT LAST_INSERT_ID()", obj, tx);
keyProperties[0].SetValue(obj, insertedId);
}
@ -32,7 +101,7 @@ namespace TWASys_App.Dapper.AExtentions
insertPropertiesString = GetColumnsString(insertProperties, columns);
await connection.QueryFirstAsync($@"
INSERT INTO {FormatTableName(tableName)}({insertPropertiesString})
VALUES ({GetColumnsString(insertProperties, columns, "@")})", obj);
VALUES ({GetColumnsString(insertProperties, columns, "@")})", obj, tx);
}
}
@ -71,17 +140,24 @@ namespace TWASys_App.Dapper.AExtentions
{
return string.Join(prefix, properties.Select(p => $"{columnNames[p.Name]} = @{p.Name}"));
}
private static string GetColumnsString(IEnumerable<PropertyInfo> properties, IReadOnlyDictionary<string, string> columnNames, string tablePrefix = null)
private static string GetColumnsString(IEnumerable<PropertyInfo> properties, IReadOnlyDictionary<string, string> columnNames, string tbName, string tablePrefix = "")
{
if (tbName != string.Empty) tbName = "tb" + tbName + "_";
if (tablePrefix == "target.")
{
return string.Join(", ", properties.Select(property => $"{tablePrefix}{columnNames[property.Name]} as {property.Name}"));
}
else if(tablePrefix == "@")
{
return string.Join(", ", properties.Select(property => $"{tablePrefix}{property.Name}"));
return string.Join(", ", properties.Select(property => $"{tablePrefix}{tbName + property.Name}"));
}
return string.Join(", ", properties.Select(property => $"{tablePrefix}{columnNames[property.Name]}"));
return string.Join(", ", properties.Select(property => $"{tablePrefix}{tbName + columnNames[property.Name].Replace("__", "")}"));
}
private static string GetColumnsString(IEnumerable<PropertyInfo> properties, IReadOnlyDictionary<string, string> columnNames, string tablePrefix = null)
{
return GetColumnsString(properties, columnNames, "", tablePrefix);
}
private static string FormatTableName(string table)
{

View File

@ -1,4 +1,6 @@
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
@ -7,10 +9,12 @@ namespace TWASys_App.Dapper.AExtentions
public class PropertiesCache
{
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> KeyProperties = new();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> FKProperties = new();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> TypeProperties = new();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> ComputedProperties = new();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IReadOnlyDictionary<string, string>> ColumnNames = new();
public static List<PropertyInfo> TypePropertiesCache(Type type)
{
if (TypeProperties.TryGetValue(type.TypeHandle, out var cachedProps))
@ -60,6 +64,28 @@ namespace TWASys_App.Dapper.AExtentions
return result;
}
public static bool IsPkAutoIncrement(PropertyInfo p)
{
// ===== Fallback by-name (nếu không thể tham chiếu typed)
var attrs = p.GetCustomAttributes(true);
bool hasKeyByName = attrs.Any(a => a.GetType().Name is "KeyAttribute");
var dbgenByName = attrs.FirstOrDefault(a => a.GetType().Name is "DatabaseGeneratedAttribute");
bool isIdentityByName = false;
if (dbgenByName != null)
{
// Tìm property "DatabaseGeneratedOption" (enum) và đọc giá trị "Identity"
var prop = dbgenByName.GetType().GetProperty("DatabaseGeneratedOption");
var val = prop?.GetValue(dbgenByName)?.ToString(); // ví dụ "Identity"
isIdentityByName = string.Equals(val, "Identity", StringComparison.OrdinalIgnoreCase);
}
if (hasKeyByName && isIdentityByName) return true;
return false;
}
public static List<PropertyInfo> KeyPropertiesCache(Type type)
{
if (KeyProperties.TryGetValue(type.TypeHandle, out var cachedProps))
@ -68,19 +94,42 @@ namespace TWASys_App.Dapper.AExtentions
}
var allProperties = TypePropertiesCache(type);
var keyProperties = allProperties.Where(p => p.GetCustomAttributes(true).Any(a => a.GetType().Name == "KeyAttribute")).ToList();
var keyProperties = allProperties.Where(IsPkAutoIncrement).ToList();
KeyProperties[type.TypeHandle] = keyProperties; // ghi cache khi miss
return keyProperties;
}
if (keyProperties.Count == 0)
public static List<PropertyInfo> FKPropertiesCache(Type type)
{
if (FKProperties.TryGetValue(type.TypeHandle, out var cachedProps))
{
var idProp = allProperties.Find(p => string.Equals(p.Name, "id", StringComparison.CurrentCultureIgnoreCase));
if (idProp != null)
return cachedProps.ToList();
}
var allProperties = TypePropertiesCache(type);
var keyProperties = allProperties.Where(HasForeignKeyAttribute).ToList();
FKProperties[type.TypeHandle] = keyProperties;
return keyProperties;
}
static bool HasForeignKeyAttribute(PropertyInfo p)
{
if (p.GetCustomAttribute<ForeignKeyAttribute>() != null) return true;
// FK đặt trên navigation và chỉ ra tên prop FK
var t = p.DeclaringType!;
foreach (var nav in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
// Fallback by-name nếu không tham chiếu DataAnnotations (tùy dự án)
var attr = nav.GetCustomAttributes(true).FirstOrDefault(a => a.GetType().Name == "ForeignKeyAttribute");
if (attr != null)
{
keyProperties.Add(idProp);
var val = attr.GetType().GetProperty("Name")?.GetValue(attr);
if (val == null && string.IsNullOrWhiteSpace(val?.ToString()))
return true;
}
}
KeyProperties[type.TypeHandle] = keyProperties;
return keyProperties;
return false;
}
public static List<PropertyInfo> ComputedPropertiesCache(Type type)
@ -95,7 +144,7 @@ namespace TWASys_App.Dapper.AExtentions
return computedProperties;
}
private static IReadOnlyDictionary<string, string> GetColumnNames(IEnumerable<PropertyInfo> props)
public static IReadOnlyDictionary<string, string> GetColumnNames(IEnumerable<PropertyInfo> props)
{
var ret = new Dictionary<string, string>();
foreach (var prop in props)

View File

@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text.Encodings.Web;
namespace TWASys_App.Models.Login
{
public sealed class LoginCheckFilter : IAsyncActionFilter, IOrderedFilter
{
public int Order => int.MinValue;
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var http = context.HttpContext;
// 1) Bỏ qua nếu endpoint cho phép anonymous
var endpoint = http.GetEndpoint();
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null ||
context.Filters.OfType<IAllowAnonymousFilter>().Any())
{
await next();
return;
}
// 2) Nếu chưa đăng nhập → redirect (web) hoặc 401 (API/Ajax)
var uid = http.Session.GetString("userID");
if (string.IsNullOrEmpty(uid))
{
// API/Ajax → trả 401 JSON; Web → redirect login
var accepts = http.Request.Headers.Accept.ToString();
var isApi = accepts.Contains("application/json", StringComparison.OrdinalIgnoreCase);
if (isApi)
{
context.Result = new JsonResult(new MessageHeader
{
ID = 1000,
Message = "Required Login",
Status = 0
});
}
else
{
var returnUrl = UrlEncoder.Default.Encode(http.Request.Path + http.Request.QueryString);
context.Result = new RedirectResult($"/login?returnUrl={returnUrl}");
}
return;
}
await next();
}
}
}

View File

@ -1,4 +1,6 @@
namespace TWASys_App.Models
using MySqlConnector;
namespace TWASys_App.Models
{
public abstract class ModelBase: IPaging
{
@ -12,6 +14,6 @@
public int PageNumber { get; set; }
public int MaxRow { get; set; }
protected MySqlConnection _connection = null!;
}
}

View File

@ -0,0 +1,12 @@
namespace TWASys_App.Models
{
public class Shared
{
private static List<string> _list = new List<string> { "80633.jpg", "806372.jpg", "806459.jpg" };
public static string RandomImages()
{
var r = new Random();
return _list[r.Next(0, _list.Count - 1)];
}
}
}

View File

@ -0,0 +1,159 @@

using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.VisualBasic;
using MySqlConnector;
using System.Data.Common;
using System.Xml.Linq;
using TWASys_App.Dapper.AExtentions;
using TWASys_App.DBModels;
namespace TWASys_App.Models
{
public class StorageModel : ModelBase
{
public long StorageTypeID { set; get; }
public string ControllerName { set; get; } = "";
public string StorageName { set; get; } = "";
public ICollection<ValidationDomain> ValidationDomains { set; get; } = new List<ValidationDomain>();
public string IpPublic { set; get; } = "";
public string IpPrivatev4 { set; get; } = "";
public string IpPrivatev6 { set; get; } = "";
public string OsName { set; get; } = "";
public string OsPlatform { set; get; } = "";
public string OsVersion { set; get; } = "";
public string OsKernel { set; get; } = "";
public string OsArch { set; get; } = "";
public string BiosSN { set; get; } = "";
public string BiosVendor { set; get; } = "";
public string BiosUUID { set; get; } = "";
public int SocketN { set; get; }
public string CpuName { set; get; } = "";
public float TotalRam { set; get; }
public string TokenID { set; get; } = "";
public string TokenValue { set; get; } = "";
public string RTokenID { set; get; } = "";
public string RTokenValue { set; get; } = "";
public override async Task<MessageHeader> AddAsync()
{
await using var con = new MySqlConnector.MySqlConnection(DBManagement.GetConnectionString(true));
await con.OpenAsync();
var trans = await con.BeginTransactionAsync();
var f = new MessageHeader();
try
{
var localServer = new LocalServer
{
IpPrivateServer = IpPrivatev4,
IpPrivateServerv6 = IpPrivatev6,
IpPublicServer = IpPublic,
PathServer = "",
SerialNumber = BiosSN,
OsVersion = OsVersion,
OsName = OsName,
OsArch = OsArch,
OsKernal = OsKernel,
SocketNum = SocketN,
CpuName = CpuName,
TotalRam = TotalRam,
BiosVender = BiosVendor,
ProductUuid = BiosUUID,
Status = 0
};//idTypeStorageServer
var storageServer = new StorageServer
{
IdEmp = null,
IdTypeStorageServer = StorageTypeID,
StorageName = StorageName,
CreateDate = DateTime.UtcNow,
ControllerID = ControllerName,
Status = 0
};
var ss_lc = new StorageServer_has_LocalServer
{
IdStorageServer = storageServer.IdStorageServer,
IdLocalServer = localServer.IdLocalServer,
CreateDate = DateTime.UtcNow,
ModifyDate = null,
Status = 0
};
var serverAuthorization = new ServerAuthorization
{
IdStorageServer = storageServer.IdStorageServer,
CreateDate = DateTime.UtcNow,
Count = 1,
Status = 0
};
var token = new Token
{
IdToken = TokenID,
AccessToken = TokenValue,
CreateDate = DateTime.UtcNow,
ExpireDate = DateTime.UtcNow.AddMonths(3),
Status = 0
};
var rT = new RefreshToken
{
IdRefreshToken = RTokenID,
IdServerAuthorization = serverAuthorization.IdServerAuthorization,
__RefreshToken = RTokenValue,
CreateDate = DateTime.UtcNow,
ExpireDate = DateTime.UtcNow.AddMonths(9),
Status = 0
};
BatchInsert bi = new BatchInsert(con, trans);
bi.AddRow(localServer);
bi.AddRow(storageServer);
bi.AddRow(ss_lc);
bi.AddRow(serverAuthorization);
bi.AddRow(token);
bi.AddRow(rT);
await bi.ExcuteQuery();
await trans.CommitAsync();
f.Status = 1;
f.Message = "OK";
}
catch (DbException ex)
{
await trans.RollbackAsync();
await trans.DisposeAsync();
f.Status = 0;
f.Message = ex.Message;
f.ID = 61031;
}
return f;
}
public override Task<MessageHeader> DeleteAsync()
{
throw new NotImplementedException();
}
public override Task<MessageHeader> UpdateAsync()
{
throw new NotImplementedException();
}
}
}

View File

@ -1,8 +1,29 @@
using AppLibs.Libs;
using AppLibs.Libs;
using Microsoft.AspNetCore.Http.Features;
using System.Net;
using System.Text;
await WSNavigation.LoadJson();
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<FormOptions>(o => {
o.MultipartBodyLengthLimit = 200_000_000; // 200 MB
});
builder.Services.AddControllers(options =>
{
options.Filters.Add<AsyncGateAttribute>();
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
builder.Services.AddDistributedMemoryCache(); // IDistributedCache in-memory
builder.Services.AddSession(o =>
{
o.IdleTimeout = TimeSpan.FromHours(8);
o.Cookie.HttpOnly = true;
o.Cookie.IsEssential = true;
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation();
// Add services to the container.
@ -23,11 +44,10 @@ app.UseRouting();
app.UseAuthorization();
app.MapStaticAssets();
app.UseSession();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.WithStaticAssets();
app.Run();

View File

@ -1,50 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net9.0-windows10.0.19041.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>TWASys_App</RootNamespace>
</PropertyGroup>
<ItemGroup Condition="$([System.String]::Copy('$(TargetFramework)').Contains('-windows'))">
<PackageReference Include="System.Management" Version="9.0.0" />
<PropertyGroup>
<TargetFrameworks>net9.0-windows;net9.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>TWASys_App</RootNamespace>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net9.0-windows'">
<PackageReference Include="System.Management" Version="9.0.10" />
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\css\atg-font\atg-admin-font.css" />
<None Include="wwwroot\css\atg-font\atg-font.css" />
<None Include="wwwroot\css\atg-lib\atg-core-min.css" />
<None Include="wwwroot\css\atg-lib\atg-core.css" />
<None Include="wwwroot\css\atg-lib\atg-upload.css" />
<None Include="wwwroot\css\atg-lib\datepicker.css" />
<None Include="wwwroot\css\atg-lib\swiper-bundle.min.css" />
<None Include="wwwroot\css\atg-lib\waves.min.css" />
<None Include="wwwroot\css\atg-ui\atg-gui.css" />
<None Include="wwwroot\css\atg-ui\table.css" />
<None Include="wwwroot\css\site.css" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AppLibs\AppLibs\AppLibs.csproj" />
</ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net9.0-windows'">
<DefineConstants>$(DefineConstants);WINDOWS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Include="wwwroot\css\atg-font\atg-admin-font.css" />
<None Include="wwwroot\css\atg-font\atg-font.css" />
<None Include="wwwroot\css\atg-lib\atg-core-min.css" />
<None Include="wwwroot\css\atg-lib\atg-core.css" />
<None Include="wwwroot\css\atg-lib\atg-upload.css" />
<None Include="wwwroot\css\atg-lib\datepicker.css" />
<None Include="wwwroot\css\atg-lib\swiper-bundle.min.css" />
<None Include="wwwroot\css\atg-lib\waves.min.css" />
<None Include="wwwroot\css\atg-ui\atg-gui.css" />
<None Include="wwwroot\css\atg-ui\table.css" />
<None Include="wwwroot\css\site.css" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.10" />
<PackageReference Include="MySqlConnector" Version="2.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.10" />
<PackageReference Include="MySqlConnector" Version="2.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
<ItemGroup>
<None Update="Keys\db\ca-cert.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Keys\db\client-cert.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Keys\db\client-key.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AppLibs\AppLibs\AppLibs.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Keys\db\ca-cert.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Keys\db\client-cert.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Keys\db\client-key.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -6,3 +6,7 @@
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
@section jsLib {
<script type="module" src="@Url.AbsoluteContent("~/js/js-page/1000.js")" js-lib></script>
}

View File

@ -1,43 +1,122 @@
<div class="c">
<div class="r j-c-center h-100vh pt-5 pb-5">
<div class="c-s-12 c-m-10 c-l-8 c-x-10 c-sx-8 w-login mt-auto mb-auto">
<div class="r-n-g j-c-center a-i-center">
<div class="d-n c-x-6 d-x-b">
<img src="~/images/img1.jpg" class="w-100" />
</div>
<div class="c-12 c-x-6">
<div class="h-100 d-f a-i-center">
<div class="ws-login d-f f-c a-i-center">
<span class="ws-title">Đăng Nhập</span>
<div class="ws-input mb-4">
<span class="label-input">Tài khoản</span>
<div class="c-input d-f a-i-center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M313.6 304c-28.7 0-42.5 16-89.6 16-47.1 0-60.8-16-89.6-16C60.2 304 0 364.2 0 438.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-25.6c0-74.2-60.2-134.4-134.4-134.4zM400 464H48v-25.6c0-47.6 38.8-86.4 86.4-86.4 14.6 0 38.3 16 89.6 16 51.7 0 74.9-16 89.6-16 47.6 0 86.4 38.8 86.4 86.4V464zM224 288c79.5 0 144-64.5 144-144S303.5 0 224 0 80 64.5 80 144s64.5 144 144 144zm0-240c52.9 0 96 43.1 96 96s-43.1 96-96 96-96-43.1-96-96 43.1-96 96-96z" /></svg>
<input type="text" class="input" placeholder="Nhập tài khoản" />
</div>
</div>
<div class="ws-input">
<span class="label-input">Mật khẩu</span>
<div class="c-input d-f a-i-center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zM264 392c0 22.1-17.9 40-40 40s-40-17.9-40-40v-48c0-22.1 17.9-40 40-40s40 17.9 40 40v48zm32-168H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z" /></svg>
<input type="password" class="input" placeholder="Nhập mật khẩu" />
</div>
</div>
<div class="ws-forgot ml-auto">
<a href="#">Quên mật khẩu?</a>
</div>
<div class="ws-btn d-f j-c-center">
<div class="btn-mask"></div>
<button class="btn btn-effect">Đăng nhập</button>
</div>
<div class="ws-signup d-f f-c a-i-center">
<span>Đăng ký tài khoản bằng ID</span>
<a href="#">Đăng Ký</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="main-login">
<div class="con-img">
<img src="~/images/login/@Shared.RandomImages()" />
</div>
<div class="c-login">
<div class="frm-login">
<div class="ws-login">
<div class="frm-header d-f f-c a-i-center">
<a app-nav href="@Url.AbsoluteContent("~/")" class="c_logo d-f j-c-center">
<img src="@Url.AbsoluteContent("~/images/logo/slogo.png")">
</a>
</div>
<div class="AWizard tabcontents">
<div class="tabcontent">
<div class="frm-header">
<h2 class="title">Sign In</h2>
<span class="d-f f-wrap desc">Bạn chưa có tài khoản? <a href="javascript:void(0)" class="ml-2" id="navSignUp">Đăng ký ngay</a></span>
</div>
<div class="frm-input mt-4">
<label>Username</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="text" class="input" placeholder="Your username" />
<span class="line"></span>
</div>
</div>
<div class="frm-input">
<label>Password</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="password" class="input" placeholder="Your password" />
<span class="line"></span>
</div>
</div>
<div class="frm-header d-f f-wrap j-c-between a-i-center">
<a href="javascript:void(0)" id="forgetPass">Forget the password?</a>
<button class="btn btn-primary btn-effect">Sign In</button>
</div>
</div>
<div class="tabcontent">
<div class="frm-header">
<h2 class="title">Don't You Remember Password?</h2>
</div>
<div class="frm-input mt-4">
<label>Địa chỉ email</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="text" class="input" placeholder="Nhập email" />
<span class="line"></span>
</div>
</div>
<div class="frm-header d-f j-c-end">
<button class="btn btn-secondary btnCB btn-effect mr-2">Quay lại</button>
<button class="btn btn-primary btn-effect">Lấy lại mật khẩu</button>
</div>
<div class="frm-header d-f f-c">
<span class="hint">
Mật khẩu mới sẽ được gửi về hộp thư trong email của bạn.
</span>
<span class="hint mt-2">
Sau khi được cấp mật khẩu mới vui lòng đổi lại mật khẩu trong trang thông tin tài khoản.
</span>
<span class="mt-2 hint">Trường hợp không nhận được email? <a href="javascript:void(0)" class="">Hãy nhắn tin cho chúng tôi!</a></span>
</div>
</div>
<div class="tabcontent">
<div class="frm-header">
<h2 class="title">Sign Up</h2>
</div>
<div class="frm-input mt-4">
<label>Địa chỉ email</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="text" class="input" placeholder="Nhập email" />
<span class="line"></span>
</div>
</div>
<div class="frm-input">
<label>Mật khẩu</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="password" class="input" placeholder="Nhập mật khẩu" />
<span class="line"></span>
</div>
</div>
<div class="frm-input">
<label>Nhập lại mật khẩu</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="password" class="input" placeholder="Nhập lại mật khẩu" />
<span class="line"></span>
</div>
</div>
<div class="frm-input">
<label>Họ & tên</label>
<div class="c-input">
<span class="ico atg a-1x atg-user"></span>
<input type="text" class="input" placeholder="Nhập họ tên" />
<span class="line"></span>
</div>
</div>
<div class="frm-header d-f j-c-end">
<button class="btn btn-secondary btnCB btn-effect mr-2">Quay lại</button>
<button class="btn btn-primary btn-effect">Đăng ký</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@section jsLib {
<script type="module" src="@Url.AbsoluteContent("~/js/js-page/10001.js")" js-lib></script>
}

View File

@ -1,7 +1,7 @@
<div class="c-logo">
<div class="logo d-f f-c a-i-center">
<img src="~/images/logo3.svg" />
<span class="mt-1 logo-name">Resort Management</span>
<img src="~/images/logo/slogo.png" />
<span class="pt-3 pb-2 logo-name">Management System</span>
</div>
<div class="d-b d-x-n hd-close">
<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 24 24" stroke="#7367f0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="d-block d-xl-none feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
@ -18,7 +18,7 @@
</div>
<div class="m-footer d-f f-c">
<span>
<b>Copyright<sup>©</sup></b> 2024 ATG Technology
<b>Copyright<sup>©</sup></b> 2025 TWA
</span>
<span class="mt-1"><b>Version: </b> 0.0.1a</span>
</div>

View File

@ -62,6 +62,7 @@
<div id="footer">
@await Html.PartialAsync("~/Views/Partial/Footer.cshtml")
</div>
@section jsLib {
<script type="module" src="@Url.AbsoluteContent("~/js/js-page/asyncLayout.js")" js-lib></script>
}

View File

@ -0,0 +1,9 @@
<section id="header">
</section>
<section id="footer">
</section>
@section jsLib {
<script type="module" src="@Url.AbsoluteContent("~/js/js-page/asyncLoginLayout.js")" js-lib></script>
}

View File

@ -23,7 +23,7 @@
user-select: none
}
a {
a {,
text-decoration: none
}
@ -197,6 +197,11 @@ h1, h2, h3, h4, h5, h6, p {
margin-left: 0;
}
.r-n-g.n{
margin-left:-20px;
margin-right:-20px
}
.r > .c, .r > [class^=c-] {
padding-right: 0;
padding-left: 0;

View File

@ -0,0 +1,165 @@
.con-img {
width: 100%;
min-height: 100%;
overflow-x: hidden;
}
.con-img > img {
height: 100%;
width: auto;
min-height: 100vw;
}
@media (min-width: 1400px) {
.con-img > img {
width: 100% !important;
max-width: 100vw;
height: auto;
min-height: auto;
max-height: 100vh;
}
}
.c-login {
position: absolute;
width: 100%;
transform: translateY(-50%);
top: 50%;
right: 0;
margin: 0 auto
}
.frm-login {
max-width: 100%;
margin: 0 25px;
}
@media (min-width: 568px) {
.frm-login {
max-width: 380px !important;
margin: 0 auto !important;
}
}
@media (min-width: 768px) {
.c-login {
right: 100px;
width: 420px;
}
.frm-login {
max-width: 100% !important
}
}
.ws-login {
box-shadow: 0 2px 3px rgba(96, 96, 96, 0.1);
background-color: #fff;
border-radius: var(--radius);
padding: 55px 35px;
}
.ws-login .c_logo {
height: 60px
}
.ws-login .title {
color: var(--color-primary)
}
.ws-login .ico {
position: absolute;
top: 40%;
transform: translateY(-50%)
}
.ws-login input {
padding-left: 25px;
}
.ws-login .title, .ws-login .desc {
}
.ws-login .hint {
font-size: .82rem;
}
.frm-inline.search button {
padding: 4px 15px;
}
.frm-inline button {
margin-left: calc(var(--radius) * -1);
}
.frm-inline input {
border-radius: var(--radius);
border: 1px solid var(--border-color);
padding: 10px 12px;
width: 100%;
font-weight: 500;
color: var(--text-color-primary)
}
.frm-group {
margin-left: -15px;
margin-right: -15px;
}
.frm-input, .frm-header {
padding: 0 15px;
margin-bottom: 25px;
}
.frm-input {
font-weight: 500;
}
.frm-input label {
color: var(--text-color-primary);
font-size: .92rem;
margin-bottom: 2px;
font-weight: 500
}
.frm-input input, .frm-input .aselect {
width: 100%;
border-bottom: 1px solid #444C6185;
background-color: #fff;
transition: .3s all ease-in-out;
font-size: .9rem;
font-weight: 400
}
.frm-input .con-aselect input {
border-radius: var(--radius);
padding: 0 15px;
border: 1px solid #444C6185
}
.frm-input input {
min-height: 35px;
line-height: 35px;
}
.frm-input .line {
position: absolute;
height: 1px;
bottom: 0;
left: 0;
z-index: 2;
width: 0;
background-color: var(--color-primary);
transition: width .4s cubic-bezier( 0.19, 0.6, 0.86, 0.01 )
}
.frm-input input:focus + .line, .frm-input input:hover + .line {
width: 100%;
}
.frm-input .c-input:not(.line) input:hover, .frm-input .c-input:not(.line) input:focus, .frm-input .con-aselect.active .aselect {
border-color: var(--color-primary);
}

View File

@ -8,13 +8,14 @@
--text-color-primary: #09205c;
--text-color-1: #5e5873;
--text-color-heading-1: #5d596c;
--text-disable: #a5a3ae
--text-disable: #a5a3ae;
--radius:10px
}
.pointer:hover{
cursor: pointer
}
.mini-scrollbar{
height: calc(100vh - 176px)
height: calc(100vh - 196px)
}
.ellipsis {
@ -26,6 +27,17 @@ html {
font-size: 18px;
font-weight: 500;
}
a{
text-decoration: none
}
body[page="10001"] .main-wrapper{
padding: 0 !important;
margin: 0
}
body[page="10001"] #header {
left:-500px
}
/*Control*/
[data-dropdown]:not(.nav-i) .sub-item {
border-radius: var(--border-radius);
@ -208,7 +220,8 @@ nav {
}
.menu-content {
height: calc(100% - 172px)
padding-top:20px;
height: calc(100% - 176px)
}
.m-footer {
@ -219,12 +232,12 @@ nav {
}
.nav-overlay {
margin-top: -.7rem;
margin-top: -10px;
background: -webkit-gradient(linear,left top,left bottom,color-stop(41%,#fff),color-stop(95%,hsla(0,0%,100%,.11)),to(hsla(0,0%,100%,0)));
background: linear-gradient(#fff 41%,hsla(0,0%,100%,.11) 95%,hsla(0,0%,100%,0));
position: absolute;
z-index: 2;
height: 50px;
height: 30px;
width: 100%;
pointer-events: none;
-webkit-filter: blur(5px);
@ -574,7 +587,7 @@ nav {
}
.btn-secondary {
color: #a8aaae;
color: #5e5873;
border-color: rgba(0, 0, 0, 0);
background: #f1f1f2;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,4 @@
window.L1000 = function () {
}
window.AScript.set("1000", true);

View File

@ -0,0 +1,26 @@
import AWizard from "/js/libs/js-AWizard.js";
window.L10001 = function () {
Waves.attach('.btn-effect', ['waves-float']);
Waves.init({ duration: 1000, delay: 200 });
var wrd1 = new AWizard(document.querySelector(".AWizard"));
const forget = document.getElementById("forgetPass");
const btnCB = document.querySelectorAll(".btnCB");
const navSignUp = document.getElementById("navSignUp")
forget.addEventListener("click", (e) => {
wrd1.nextPage(1);
});
btnCB.forEach((el) => {
el.addEventListener("click", (e) => {
ComeBack(e, wrd1);
});
});
navSignUp.addEventListener("click", (e) => {
wrd1.nextPage(2);
});
}
function ComeBack(e, wrd) {
wrd.nextPage(0);
}
window.AScript.set("10001", true);

View File

@ -38,9 +38,15 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
</div>
</div>
<div class="form-group d-f f-c">
<label for="pathServer">Controller Name</label>
<label for="controllerName">Controller Name</label>
<div class="input-group">
<input id="pathServer" type="text" placeholder="Controller Name" validation-isEmpty />
<input id="controllerName" type="text" placeholder="Controller Name" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
<label for="storageName">Storage Name</label>
<div class="input-group">
<input id="storageName" type="text" placeholder="Storage Name" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
@ -103,9 +109,9 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
</div>
</div>
<div class="form-group d-f f-c">
<label for="expiredDate">SharePoint Path</label>
<label for="sharepointPath">SharePoint Path</label>
<div class="input-group">
<input id="expiredDate" type="password" placeholder="Client ID" validation-isEmpty />
<input id="sharepointPath" type="text" placeholder="Client ID" validation-isEmpty />
</div>
</div>
</div>
@ -140,7 +146,7 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
<div class="form-group d-f f-c">
<label for="clientID">OS Platform</label>
<div class="input-group">
<input id="osName" data-id="osPlatform" type="text" placeholder="OS Platform" validation-isEmpty />
<input id="osPlatform" data-id="osPlatform" type="text" placeholder="OS Platform" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
@ -158,7 +164,7 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
<div class="form-group d-f f-c">
<label for="clientID">OS Architecture</label>
<div class="input-group">
<input id="osKernel" data-id="osArch" type="text" placeholder="OS Architecture" validation-isEmpty />
<input id="osArch" data-id="osArch" type="text" placeholder="OS Architecture" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
@ -203,30 +209,51 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
<h5 class="mb-2">Server Authenicator</h4>
</div>
<div class="form-group d-f f-c">
<label for="clientID">IP Server</label>
<label for="idToken">Token ID</label>
<div class="input-group">
<input id="clientID" type="text" placeholder="Client ID" validation-isEmpty />
<input id="idToken" type="text" placeholder="Token ID" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
<label for="clientID">Machine ID</label>
<label for="vToken">Token Value</label>
<div class="input-group">
<input id="clientID" type="text" placeholder="Client ID" validation-isEmpty />
<input id="vToken" type="password" placeholder="Token Value" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
<label for="clientID">OS Version</label>
<label for="idRefreshToken">Refresh Token ID</label>
<div class="input-group">
<input id="clientID" type="text" placeholder="Client ID" validation-isEmpty />
<input id="idRefreshToken" type="text" placeholder="Refresh Token ID" validation-isEmpty />
</div>
</div>
<div class="form-group d-f f-c">
<label for="clientID">Proccessor ID</label>
<label for="refreshTokenValue">Refresh Token Value</label>
<div class="input-group">
<input id="clientID" type="text" placeholder="Client ID" validation-isEmpty />
<input id="refreshTokenValue" type="password" placeholder="Refresh Token Value" validation-isEmpty />
</div>
</div>
</div>
<div class="tabcontent">
<div class="form-group">
<h5 class="mb-2">Storage Data Summary</h4>
</div>
<div class="form-group mb-0 d-f">
<label>Storage Server Type</label>
<span class="ml-2"></span>
</div>
<div class="form-group mb-0 d-f">
<label>Controller Name</label>
<span class="ml-2"></span>
</div>
<div class="form-group mb-0 d-f">
<label>Storage Name</label>
<span class="ml-2"></span>
</div>
<div class="form-group mb-0 d-f">
<label>Validation Domains</label>
<span class="ml-2"></span>
</div>
</div>
</div>
</div>
<div class="tabcontent">
@ -262,24 +289,99 @@ window.L6101 = function () {
var ov = new AOverlay(document.body);
ov.createOverlay();
const $v = id => (document.getElementById(id)?.value ?? '').trim();
var ele1 = new ASpinButton(document.getElementById("totalSize"));
var ele2 = new AMultiTag(document.getElementById("listStorage"));
var slider = new AModal(tmp);
slider.createModal("CustomForm", "slider-right");
var Scrollbar = window.Scrollbar;
Scrollbar.init(slider.CustomContainer.querySelector(".slider-scrollbar"), window.scroll_options);
const mScroll = Scrollbar.init(slider.CustomContainer.querySelector(".slider-scrollbar"), window.scroll_options);
slider.overlay.isCloseOverlay(true);
var tabs = new ATab(slider.CustomContainer.querySelector(".atabs"), slider.CustomContainer.querySelector(".StorageTabs"));
var wrd1 = new AWizard(slider.CustomContainer.querySelector(".AWizard"));
var as = new ASelect(slider.CustomContainer.querySelectorAll(".aselect"));
window.testV = as;
var asIdType = as.get(0);
wrd1.on("onBeforeBack", (evt) => {
mScroll.scrollTo(0, 0);
});
wrd1.on("onAfterNext", (evt) => {
if (evt.indexPage > 0) {
if (as.get(0).isLockElement() || as.get(1).isLockElement()) {
return;
}
switch (asIdType.getSelectedItem().vSearch) {
case "Microsoft Cloud":
break;
case "Physical Server":
if (evt.indexPage > 3) {
(async () => {
const fd = new FormData();
fd.append('StorageTypeID', asIdType.getSelectedItem()?.id ?? '');
fd.append('ControllerName', $v('controllerName'));
fd.append('StorageName', $v('storageName'));
fd.append('IpPublic', $v('ipPublic'));
fd.append('IpPrivatev4', $v('ipPrivatev4'));
fd.append('IpPrivatev6', $v('ipPrivatev6'));
fd.append('OsName', $v('osName'));
fd.append('OsPlatform', $v('osPlatform'));
fd.append('OsVersion', $v('osVersion'));
fd.append('OsKernel', $v('osKernel'));
fd.append('OsArch', $v('osArch'));
fd.append('BiosSN', $v('biosSerial'));
fd.append('BiosVendor', $v('biosVender'));
fd.append('BiosUUID', $v('biosUUID'));
const i = 0;
as.get(1).multiSelectedItem.forEach((item) => {
fd.append(`ValidationDomains[${i}].IdValidationDomain`, item.getAttribute("data-value"));
});
fd.append('SocketN', $v('socketN'));
fd.append('CpuName', $v('cpuName'));
fd.append('TotalRam', $v('totalRam'));
fd.append('TokenID', $v('idToken'));
fd.append('TokenValue', $v('vToken'));
fd.append('RTokenID', $v('idRefreshToken'));
fd.append('RTokenValue', $v('refreshTokenValue'))
const response = await fetch("/Storage/SetStorageData", {
method: 'POST',
body: fd
});
})();
}
break;
}
}
});
wrd1.on("onBeforeNext", (evt) => {
mScroll.scrollTo(0, 0);
if (evt.indexPage == 0) {
if (asIdType.isLockElement() && asVD.isLockElement()) {
if (as.get(0).isLockElement() || as.get(1).isLockElement()) {
wrd1.isStopNextPage = true;
return;
} else {
wrd1.isStopNextPage = false;
}
let flag = false;
if ($v('controllerName').length == 0) {
flag = true;
}
if ($v('storageName').length == 0) {
flag = true;
}
if (as.get(1).multiSelectedItem.length == 0) {
flag = true;
}
if (flag) {
wrd1.isStopNextPage = true;
return;
} else {
@ -289,9 +391,11 @@ window.L6101 = function () {
case "Microsoft Cloud":
wrd1.showPage(1);
wrd1.hidePage(2);
wrd1.hidePage(3);
break;
case "Physical Server":
wrd1.showPage(2);
wrd1.showPage(3);
wrd1.hidePage(1);
let promise = new Promise(async function (resolve, reject) {
const response = await fetch(`/Storage/GetSysInfo`, {
@ -305,10 +409,43 @@ window.L6101 = function () {
const autoF = new AAutoFill(document.querySelector(".awStorageConnector"));
autoF.fill(data);
}
});
});
break;
}
}e
} else if (evt.indexPage == 1)
{
}
else if (evt.indexPage == 2) {
(async () => {
const response = await fetch(`/Storage/GenerationAccessToken`, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
const data = await response.json();
if (data) {
document.getElementById("idToken").value = data.idToken;
document.getElementById("vToken").value = data.tokenValue;
}
})();
(async () => {
const response = await fetch(`/Storage/GenerationAccessToken`, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
const data = await response.json();
if (data) {
document.getElementById("idRefreshToken").value = data.idToken;
document.getElementById("refreshTokenValue").value = data.tokenValue;
}
})();
}
}, true);
var asVD = as.get(1);
@ -321,6 +458,7 @@ window.L6101 = function () {
let promise = new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open("GET", window.GetAbsoluteURL("/Storage/GetTypeStorage"));
xhr.setRequestHeader('Accept', 'application/json; charset=UTF-8');
var f = function (ev) {
if (ev.currentTarget.readyState == 4) {
if (ev.currentTarget.status == 200) {
@ -344,6 +482,7 @@ window.L6101 = function () {
let promise1 = new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open("GET", window.GetAbsoluteURL("/Storage/GetValidationDomain"));
xhr.setRequestHeader('Accept', 'application/json; charset=UTF-8');
var f = function (ev) {
if (ev.currentTarget.readyState == 4) {
if (ev.currentTarget.status == 200) {
@ -374,7 +513,7 @@ window.L6101 = function () {
asAddStorage.on("click_btAddStorage", (e) => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "/Storage/AddStorageServer");
xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
xhr.setRequestHeader('Accept', 'application/json; charset=UTF-8');
var data = {
"Name": document.getElementById("inpType").value
};

View File

@ -14,6 +14,7 @@ class AsyncLayout extends ALayout {
super.dispose();
}
renderMenu() {
console.log("ÁDASD");
this.isLoaded = true;
var asyncStyleSheets = [
'https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap',

View File

@ -0,0 +1,39 @@
import ALayout from '/js/libs/js-ALayout.js'
class LoginLayout extends ALayout {
constructor() {
super();
this.isLoaded = false;
}
dispose() {
this.isLoaded = false;
window.app.removeSytemEventParent(window.app.lName);
window.app.removeCustomEventParent(window.app.lName);
super.dispose();
}
renderMenu() {
this.isLoaded = true;
var asyncStyleSheets = [
'https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap',
'/css/atg-font/atg-admin-font.css',
'/css/atg-lib/waves.min.css',
'/css/pages/login.css'
];
window.app.loadCSS(asyncStyleSheets);
window.app.initNavs("Login");
var sOption = {
damping: (window.getOS() == "Android") ? .06 : .04,
thumbMinSize: 25,
renderByPixel: true,
alwaysShowTracks: true,
continuousScrolling: true
};
window.Scrollbar.use(window.OverscrollPlugin);
window.app.initScrollBar();
}
}
window.ALayout.set("Login", new LoginLayout());
window.AScript.set("asyncLoginLayout", true);

View File

@ -106,12 +106,12 @@ export default class AWizard extends ATab {
btnNext_Click(e, idx) {
this.trigger("onBeforeNext", { "currentPage": this.ctabs[idx], "indexPage": idx, "currentButton": e.currentTarget });
if (this.isStopNextPage) return;
console.log(idx);
this.selectedTab(this.checkSelectedNext(idx));
this.trigger("onAfterNext");
this.trigger("onAfterNext", { "currentPage": this.ctabs[idx], "indexPage": idx + 1, "currentButton": e.currentTarget });
}
btnBack_Click(e, idx) {
this.trigger("onBeforeBack", { "currentPage": this.ctabs[idx], "indexPage": idx, "currentButton": e.currentTarget });
this.selectedTab(this.checkSelectedBack(idx));
}
btnFinish_Click(e) {

View File

@ -541,6 +541,7 @@ class AApp extends window.AObject {
this.metaPage = document.head.querySelector("meta[name=idPage]");
this.pageName = this.metaPage.getAttribute("pageName");
this.lName = this.metaPage.getAttribute("layName");
console.log(this.lName);
var tmp = document.querySelector(container);
this.mainApp = tmp.querySelector("[main-content]") ? tmp.querySelector("[main-content]") : tmp;
var f = function (ev) {
@ -688,6 +689,7 @@ class AApp extends window.AObject {
doc: doc,
dynamicF: a.dynamicF
};
this.setContentPage(obj, url);
} else {
this.getPage(url, result)
@ -721,7 +723,9 @@ class AApp extends window.AObject {
document.title = page.title + " - " + this.pageName;
var meta = document.head.querySelector("meta[name=idPage]");
document.body.setAttribute("page", page.idPage);
meta.content = page.idPage;
this.lName = page.lName;
meta.setAttribute("layName", page.lName);
this.loadContentPage(page.html);
window.history.pushState({"url":url}, page.title, url);
@ -821,6 +825,7 @@ class AApp extends window.AObject {
}).bind(this)();
}
loadedLayout() {
console.log(this.lName);
if (this.lName !== "None") {
const l = window.ALayout.get(this.lName);
if (!l.isLoaded) {
@ -831,7 +836,6 @@ class AApp extends window.AObject {
}
}
setLayout(o) {
var oP = new DOMParser();
var pHtml = oP.parseFromString(o.Content, 'text/html');
(function () {