帳號管理功能完成

master
嘉祥 詹 2023-11-02 18:52:18 +08:00
parent 4c610d50c1
commit 58a60eeeac
19 changed files with 2028 additions and 86 deletions

View File

@ -42,7 +42,7 @@ namespace Journeys_WantHome.Controllers
[Route("BackEndApi")] [Route("AuthApi")]
public class AuthApiController : ControllerBase public class AuthApiController : ControllerBase
{ {
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
@ -57,8 +57,369 @@ namespace Journeys_WantHome.Controllers
this._httpContextAccessor = httpContextAccessor; this._httpContextAccessor = httpContextAccessor;
} }
[Route("addEditGetUser")]
public ActionResult AddEditGetUser(IFormCollection obj) {
updateUserResult ret = new updateUserResult();
authToken token = new authToken(this._httpContextAccessor);
if (token.user_isLogin == false)
{
HttpContext.Response.Cookies.Delete("token_key");
ret.ret = "no";
ret.err_code = "99999";
ret.message = "非登入狀態!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (token.user_perm != "system")
{
ret.ret = "no";
ret.err_code = "90001";
ret.message = "此帳號無此api使用權限!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
string method = obj["method"].ToString();
if (method == "") {
ret.ret = "no";
ret.err_code = "0001";
ret.message = "沒有method參數";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (method == "add") {
string user_type = obj["user_type"].ToString();
string user_perm = obj["user_perm"].ToString();
if (user_type == "") {
ret.ret = "no";
ret.err_code = "0002";
ret.message = "沒有user_type參數";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
//N為E白板帳號
if (user_type == "N")
{
string user_id = obj["user_elabName"].ToString();
user newUser = conn.QueryFirstOrDefault<user>("select * from users where user_id = @user_id ", new { user_id = user_id });
if (newUser != null)
{
ret.ret = "no";
ret.err_code = "0003";
ret.message = "此帳號已經存在於系統!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
new_userdata elabUser;
try
{
elabUser = elabConn.QueryFirstOrDefault<new_userdata>("select * from new_userdata where userid = @user_id", new { user_id = user_id });
}
catch (Exception ex) {
ret.ret = "no";
ret.err_code = "90001";
ret.message = ex.Message;
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (elabUser == null)
{
ret.ret = "no";
ret.err_code = "0004";
ret.message = "E白板無此帳號!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
string user_uid = GlobalClass.CreateRandomCode(12);
newUser = new user();
newUser.user_uid = user_uid;
newUser.user_name = elabUser.username;
newUser.user_id = elabUser.userid;
newUser.user_email = elabUser.mail;
newUser.user_type = user_type;
newUser.user_onjob = "Y";
newUser.user_perm = user_perm;
newUser.user_ishidden = "N";
newUser.user_createdate = DateTime.Now;
if (user_perm == "")
{
ret.ret = "no";
ret.err_code = "0009";
ret.message = "無此帳號的權限設定值!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
conn.Insert(newUser);
ret.ret = "yes";
ret.user = newUser;
}
else {
string user_id = obj["user_id"].ToString();
string user_pwd = obj["user_pwd"].ToString();
string user_uid = GlobalClass.CreateRandomCode(12);
string user_name = obj["user_name"].ToString();
string user_email = obj["user_email"].ToString();
if (user_id == "") {
ret.ret = "no";
ret.err_code = "0006";
ret.message = "請輸入帳號ID!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (user_name == "")
{
ret.ret = "no";
ret.err_code = "0006";
ret.message = "請輸入帳號名稱!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (user_perm == "") {
ret.ret = "no";
ret.err_code = "0009";
ret.message = "無此帳號的權限設定值!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (GlobalClass.isEmail(user_email) == false) {
ret.ret = "no";
ret.err_code = "0007";
ret.message = "請輸入正確EMail!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
user newUser = conn.QueryFirstOrDefault<user>("select * from users where user_id = @user_id ", new { user_id = user_id });
if (newUser != null)
{
ret.ret = "no";
ret.err_code = "0003";
ret.message = "此帳號已經存在於系統!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
new_userdata elabUser = elabConn.QueryFirstOrDefault("select * from new_userdata where userid = @user_id", new { user_id = user_id });
if (elabUser != null)
{
ret.ret = "no";
ret.err_code = "0005";
ret.message = "E白板系統內有此帳號ID請換帳號或改以E白板帳號加入!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
newUser = new user();
newUser.user_uid = user_uid;
newUser.user_id = user_id;
newUser.user_name = user_name;
newUser.user_pwd = user_pwd;
newUser.user_email = user_email;
newUser.user_type = user_type;
newUser.user_onjob = "Y";
newUser.user_perm = user_perm;
newUser.user_ishidden = "N";
newUser.user_createdate = DateTime.Now;
conn.Insert(newUser);
ret.ret = "yes";
ret.user = newUser;
}
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (method == "edit") {
string user_type = obj["user_type"].ToString();
string user_uid = obj["user_uid"].ToString();
string user_perm = obj["user_perm"].ToString();
if (user_type == "")
{
ret.ret = "no";
ret.err_code = "0002";
ret.message = "沒有user_type參數";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (user_perm == "")
{
ret.ret = "no";
ret.err_code = "0009";
ret.message = "無此帳號的權限設定值!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
user editUser = conn.QueryFirstOrDefault<user>("select * from users where user_uid = @user_uid and user_type = @user_type", new { user_uid = user_uid, user_type = user_type });
if (editUser == null) {
ret.ret = "no";
ret.err_code = "0008";
ret.message = "沒有此用戶資料!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
//N為E白板帳號
if (user_type == "N")
{
editUser.user_perm = user_perm;
}
else {
string user_pwd = obj["user_pwd"].ToString();
string user_name = obj["user_name"].ToString();
string user_email = obj["user_email"].ToString();
editUser.user_perm = user_perm;
if (user_name == "")
{
ret.ret = "no";
ret.err_code = "0006";
ret.message = "請輸入帳號名稱!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (GlobalClass.isEmail(user_email) == false)
{
ret.ret = "no";
ret.err_code = "0007";
ret.message = "請輸入正確EMail!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (user_pwd != "") {
editUser.user_pwd = user_pwd;
}
editUser.user_name = user_name;
editUser.user_email = user_email;
}
conn.Update<user>(editUser);
ret.ret = "yes";
ret.user = editUser;
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (method == "del") {
string user_uid = obj["user_uid"].ToString();
user editUser = conn.QueryFirstOrDefault<user>("select * from users where user_ishidden = 'N' and user_uid = @user_uid ", new { user_uid = user_uid });
if (editUser == null)
{
ret.ret = "no";
ret.err_code = "0008";
ret.message = "沒有此用戶資料!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
editUser.user_ishidden = "Y";
conn.Update(editUser);
if (editUser.user_lastlogintime == "") {
conn.Delete(editUser);
}
ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (method == "get") {
string user_uid = obj["user_uid"].ToString();
user editUser = conn.QueryFirstOrDefault<user>("select * from users where user_ishidden = 'N' and user_uid = @user_uid", new { user_uid = user_uid });
if (editUser == null)
{
ret.ret = "no";
ret.err_code = "0008";
ret.message = "沒有此用戶資料!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
ret.ret = "yes";
ret.user = editUser;
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
[Route("elab_UserList")]
public ActionResult Elab_UserList(IFormCollection obj) {
elabUserListResult ret = new elabUserListResult();
authToken token = new authToken(this._httpContextAccessor);
if (token.user_isLogin == false)
{
HttpContext.Response.Cookies.Delete("token_key");
ret.ret = "no";
ret.err_code = "99999";
ret.message = "非登入狀態!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (token.user_perm != "system")
{
ret.ret = "no";
ret.err_code = "90001";
ret.message = "此帳號無此api使用權限!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
ret.userList = elabConn.Query<new_userdata>("select * from new_userdata where onjob = 0 order by usersn desc ").ToList();
ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
[Route("userList")]
public ActionResult UserList(IFormCollection obj) {
userListResult ret = new userListResult();
authToken token = new authToken(this._httpContextAccessor);
if (token.user_isLogin == false)
{
HttpContext.Response.Cookies.Delete("token_key");
ret.ret = "no";
ret.err_code = "99999";
ret.message = "非登入狀態!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (token.user_perm != "system") {
ret.ret = "no";
ret.err_code = "90001";
ret.message = "此帳號無此api使用權限!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
ret.userList = conn.Query<user>("select * from users where user_ishidden = 'N' order by user_sn desc").ToList();
ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
[Route("signin")] [Route("signin")]
public ActionResult Signin(FormCollection obj) { public ActionResult Signin(IFormCollection obj) {
signinResult ret = new signinResult(); signinResult ret = new signinResult();
string input_ID = obj["id"].ToString(); string input_ID = obj["id"].ToString();
@ -68,6 +429,13 @@ namespace Journeys_WantHome.Controllers
string sys_ID = GlobalClass.appsettings("Admin:id"); string sys_ID = GlobalClass.appsettings("Admin:id");
string sys_PWD = GlobalClass.Sha256(GlobalClass.appsettings("Admin:pwd")); string sys_PWD = GlobalClass.Sha256(GlobalClass.appsettings("Admin:pwd"));
if (input_ID == "") {
ret.ret = "no";
ret.err_code = "0001";
ret.message = "帳號或密碼錯誤!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
//判斷是否為系統預設帳號 //判斷是否為系統預設帳號
if (input_ID == sys_ID) if (input_ID == sys_ID)
{ {
@ -90,7 +458,8 @@ namespace Journeys_WantHome.Controllers
string token_key = GlobalClass.CreateRandomCode(24); string token_key = GlobalClass.CreateRandomCode(24);
adminToken.user_uid = GlobalClass.appsettings("Admin:id"); adminToken.user_uid = GlobalClass.appsettings("Admin:uid");
adminToken.user_id = GlobalClass.appsettings("Admin:id");
adminToken.token_isremember = input_isRemember; adminToken.token_isremember = input_isRemember;
adminToken.token_key = token_key; adminToken.token_key = token_key;
adminToken.token_createdate = DateTime.Now; adminToken.token_createdate = DateTime.Now;
@ -113,7 +482,7 @@ namespace Journeys_WantHome.Controllers
} }
else { else {
//非系統帳號 //非系統帳號
user webUser = conn.QueryFirstOrDefault<user>("select * from users where user_ishidden = 'N' and user_uid = @user_uid", new { user_uid = input_ID}); user webUser = conn.QueryFirstOrDefault<user>("select * from users where user_ishidden = 'N' and user_id = @user_id", new { user_id = input_ID});
if (webUser == null) if (webUser == null)
{ {
@ -130,9 +499,12 @@ namespace Journeys_WantHome.Controllers
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} }
webUser.user_lastlogintime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
if (webUser.user_type == "Y") if (webUser.user_type == "Y")
{ {
if (input_PWD != webUser.user_pwd) { if (input_PWD != webUser.user_pwd)
{
ret.ret = "no"; ret.ret = "no";
ret.err_code = "0004"; ret.err_code = "0004";
ret.message = "密碼錯誤!"; ret.message = "密碼錯誤!";
@ -141,16 +513,18 @@ namespace Journeys_WantHome.Controllers
} }
else else
{ {
new_userdata elabUser = elabConn.QueryFirstOrDefault<new_userdata>("select * from new_userdata where userid = @userid", new { userid = webUser.user_id}); new_userdata elabUser = elabConn.QueryFirstOrDefault<new_userdata>("select * from new_userdata where userid = @userid", new { userid = webUser.user_id });
if (input_PWD != GlobalClass.Sha256(elabUser.userpw)) { if (input_PWD != GlobalClass.Sha256(elabUser.userpw))
{
ret.ret = "no"; ret.ret = "no";
ret.err_code = "0004"; ret.err_code = "0004";
ret.message = "密碼錯誤!"; ret.message = "密碼錯誤!";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} }
if (elabUser.onjob == 1) { if (elabUser.onjob == 1)
{
webUser.user_onjob = "N"; webUser.user_onjob = "N";
conn.Update(webUser); conn.Update(webUser);
@ -160,6 +534,7 @@ namespace Journeys_WantHome.Controllers
ret.message = "此帳號已經離職,無法登入"; ret.message = "此帳號已經離職,無法登入";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} }
}
token userToken = new token(); token userToken = new token();
@ -172,13 +547,15 @@ namespace Journeys_WantHome.Controllers
string token_key = GlobalClass.CreateRandomCode(24); string token_key = GlobalClass.CreateRandomCode(24);
userToken.user_uid = input_ID; userToken.user_uid = webUser.user_uid;
userToken.user_id = input_ID;
userToken.token_isremember = input_isRemember; userToken.token_isremember = input_isRemember;
userToken.token_key = token_key; userToken.token_key = token_key;
userToken.token_createdate = DateTime.Now; userToken.token_createdate = DateTime.Now;
userToken.token_expireddate = DateTime.Now.AddMinutes(intexpireMin); userToken.token_expireddate = DateTime.Now.AddMinutes(intexpireMin);
conn.Insert<token>(userToken); conn.Insert<token>(userToken);
conn.Update<user>(webUser);
CookieOptions options = new CookieOptions(); CookieOptions options = new CookieOptions();
@ -192,8 +569,13 @@ namespace Journeys_WantHome.Controllers
ret.ret = "yes"; ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} }
}
ret.ret = "no";
ret.err_code = "9999";
ret.message = "無參數錯誤";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} }
@ -204,5 +586,29 @@ namespace Journeys_WantHome.Controllers
public string err_code = "0000"; public string err_code = "0000";
public string message = ""; public string message = "";
} }
public class userListResult
{
public string ret = "no";
public string err_code = "0000";
public string message = "";
public List<user> userList = new List<user>();
}
public class elabUserListResult
{
public string ret = "no";
public string err_code = "0000";
public string message = "";
public List<new_userdata> userList = new List<new_userdata>();
}
public class updateUserResult
{
public string ret = "no";
public string err_code = "0000";
public string message = "";
public user user = new user();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Journeys_WantHome.Models; using Journeys_WantHome.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Diagnostics; using System.Diagnostics;
@ -7,22 +8,70 @@ namespace Journeys_WantHome.Controllers
public class HomeController : Controller public class HomeController : Controller
{ {
private readonly ILogger<HomeController> _logger; private readonly ILogger<HomeController> _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
private authToken _objToken;
public HomeController(ILogger<HomeController> logger)
public HomeController(ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor)
{ {
_logger = logger; _logger = logger;
this._httpContextAccessor = httpContextAccessor;
this._objToken = new authToken(this._httpContextAccessor);
} }
public IActionResult Index() public IActionResult UserList()
{ {
if (checkToken() == false)
{
HttpContext.Response.Cookies.Delete("token_key");
return Redirect("~/Root/Login");
}
if (this._objToken.user_perm != "system") {
return Redirect("~/");
}
return View(); return View();
} }
public IActionResult Privacy() public IActionResult Dashboard()
{ {
if (checkToken() == false)
{
HttpContext.Response.Cookies.Delete("token_key");
return Redirect("~/Root/Login");
}
return View(); return View();
} }
public Boolean checkToken()
{
this._objToken = new authToken(this._httpContextAccessor);
if (this._objToken.user_isLogin == false)
{
HttpContext.Response.Cookies.Delete("token_key");
return false;
}
@ViewData["user_name"] = this._objToken.user_name;
ViewData["user_permtype"] = "一般使用者";
if (this._objToken.user_perm == "system")
{
ViewData["authMenu"] = "display:block;";
ViewData["user_permtype"] = "管理者";
}
else {
ViewData["authMenu"] = "display:none;";
}
return true;
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error() public IActionResult Error()
{ {

View File

@ -19,6 +19,8 @@ public class DbTableClass
public string user_uid { get; set; } = ""; public string user_uid { get; set; } = "";
public string user_id { get; set; } = "";
public string token_isremember { get; set; } = "N"; public string token_isremember { get; set; } = "N";
public DateTime token_createdate { get; set; } = DateTime.Now; public DateTime token_createdate { get; set; } = DateTime.Now;
@ -56,7 +58,7 @@ public class DbTableClass
public DateTime user_createdate { get; set; } = DateTime.Now; public DateTime user_createdate { get; set; } = DateTime.Now;
public string user_lastlogintime { get; set; } = DateTime.Now; public string user_lastlogintime { get; set; } = "";
} }
@ -73,19 +75,19 @@ public class DbTableClass
public string username { get; set; } = ""; public string username { get; set; } = "";
public int? maincategoryid { get; set; } = 1; public int maincategoryid { get; set; } = 1;
public int? subcategoryid { get; set; } = 1; public int subcategoryid { get; set; } = 1;
public int? grade { get; set; } = 0; public int grade { get; set; } = 0;
public string mail { get; set; } = ""; public string mail { get; set; } = "";
public string mailto { get; set; } = ""; public string mailto { get; set; } = "";
public int? onjob { get; set; } = 0; public int onjob { get; set; } = 0;
public int? permission { get; set; } = 0; public int permission { get; set; } = 0;
} }

View File

@ -168,15 +168,6 @@ public static class GlobalClass
return (Image)destinationImage; return (Image)destinationImage;
} }
public static void sendLineMessage(string uid, string messageJson)
{
string channelAccessToken = GlobalClass.appsettings("Line:access_token");
var bot = new isRock.LineBot.Bot(channelAccessToken);
bot.PushMessageWithJSON(uid, messageJson);
}
/// <summary> /// <summary>
/// base 64字串格式的圖片轉成Image物件 /// base 64字串格式的圖片轉成Image物件
/// </summary> /// </summary>

View File

@ -13,6 +13,7 @@ using System.Data.SqlClient;
using static DbTableClass; using static DbTableClass;
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using Microsoft.Extensions.Options;
public class authToken public class authToken
{ {
@ -49,12 +50,15 @@ public class authToken
var tokenData = dbConn.sqlConnection().Query("select * from token where token_key = @token_key", new { token_key = token_key }); var tokenData = dbConn.sqlConnection().Query("select * from token where token_key = @token_key", new { token_key = token_key });
CookieOptions cookieOptions = new CookieOptions(); //CookieOptions cookieOptions = new CookieOptions();
//cookieOptions.Secure = true;
//cookieOptions.Expires = DateTime.Now.AddMinutes(intexpireMin);
if (tokenData.Count() == 0) if (tokenData.Count() == 0)
{ {
_httpContextAccessor.HttpContext.Response.Cookies.Delete("token_key");
user_isLogin = false; user_isLogin = false;
error_msg = "not this account"; error_msg = "not this account";
@ -84,6 +88,16 @@ public class authToken
"where token_key = @token_key", new { token_expireddate = DateTime.Now.AddMinutes(intMin), token_key = token_key }); "where token_key = @token_key", new { token_expireddate = DateTime.Now.AddMinutes(intMin), token_key = token_key });
dbConn.closeConn(); dbConn.closeConn();
CookieOptions options = new CookieOptions()
{
Secure = true,
Expires = DateTime.Now.AddMinutes(intMin)
};
//_httpContextAccessor.HttpContext.Response.Cookies.Delete("web_token_key");
_httpContextAccessor.HttpContext.Response.Cookies.Append("token_key", token_key, options);
return; return;
} }
else { else {
@ -125,6 +139,16 @@ public class authToken
dbConn.sqlConnection().Execute("update token set token_expireddate = @token_expireddate " + dbConn.sqlConnection().Execute("update token set token_expireddate = @token_expireddate " +
"where token_key = @token_key", new { token_expireddate = DateTime.Now.AddMinutes(intMin), token_key = token_key }); "where token_key = @token_key", new { token_expireddate = DateTime.Now.AddMinutes(intMin), token_key = token_key });
CookieOptions options = new CookieOptions()
{
Secure = true,
Expires = DateTime.Now.AddMinutes(intMin)
};
//_httpContextAccessor.HttpContext.Response.Cookies.Delete("web_token_key");
_httpContextAccessor.HttpContext.Response.Cookies.Append("token_key", token_key, options);
dbConn.closeConn(); dbConn.closeConn();
} }

View File

@ -26,6 +26,6 @@ app.UseAuthorization();
app.MapControllerRoute( app.MapControllerRoute(
name: "default", name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"); pattern: "{controller=Home}/{action=Dashboard}/{id?}");
app.Run(); app.Run();

View File

@ -0,0 +1,14 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
Layout = "_LooperLayout";
}
@section Style {
}
@section Script {
<script src="~/assets/javascript/custom/dashboard.js?v=1"></script>
}

View File

@ -1,8 +0,0 @@
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

View File

@ -1,6 +0,0 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>

153
Views/Home/UserList.cshtml Normal file
View File

@ -0,0 +1,153 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
Layout = "_LooperLayout";
}
@section Style {
<link rel="stylesheet" href="~/assets/vendor/datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css">
}
@section Script {
<script src="~/assets/vendor/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="~/assets/vendor/datatables.net-responsive/js/dataTables.responsive.min.js"></script>
<script src="~/assets/vendor/datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js"></script>
<script src="~/assets/javascript/pages/dataTables.bootstrap.js"></script>
<script src="~/assets/javascript/custom/userlist.js?v=1"></script>
}
<!-- .page-inner -->
<div class="page-inner">
<!-- .page-title-bar -->
<header class="page-title-bar">
<!-- .breadcrumb -->
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item active">
<a href="#"><i class="breadcrumb-icon fa fa-angle-left mr-2"></i>使用者清單</a>
</li>
</ol>
</nav><!-- /.breadcrumb -->
<!-- title -->
<h1 class="page-title"> 系統使用者清單 </h1>
<p class="text-muted"> </p><!-- /title -->
</header><!-- /.page-title-bar -->
<!-- .page-section -->
<div class="page-section">
<button type="button" id="userNewModal" class="btn btn-primary btn-floated position-absolute" title="Add new client"><i class="fa fa-plus"></i></button>
<!-- .card -->
<div class="card card-fluid">
<!-- .card-body -->
<div class="card-body">
<!-- .table -->
<table id="dt-responsive" class="table dt-responsive nowrap w-100">
<thead>
<tr>
<th> 姓名 </th>
<th> 帳號 </th>
<th> 類型 </th>
<th> 權限 </th>
<th> 上次登入 </th>
<th> 功能 </th>
</tr>
</thead>
<tfoot>
<tr>
<th> 姓名 </th>
<th> 帳號 </th>
<th> 類型 </th>
<th> 權限 </th>
<th> 上次登入 </th>
<th> 功能 </th>
</tr>
</tfoot>
</table><!-- /.table -->
</div><!-- /.card-body -->
</div><!-- /.card -->
</div><!-- /.page-section -->
</div><!-- /.page-inner -->
<!-- Keep in mind that modals should be placed outsite of page sidebar -->
<!-- .modal -->
<form id="clientNewForm" name="clientNewForm">
<div class="modal fade" id="clientNewModal" tabindex="-1" role="dialog" aria-labelledby="clientNewModalLabel" aria-hidden="true">
<!-- .modal-dialog -->
<div class="modal-dialog" role="document">
<!-- .modal-content -->
<div class="modal-content">
<!-- .modal-header -->
<div class="modal-header">
<h6 id="clientNewModalLabel" class="modal-title inline-editable">
<span class="sr-only">Client name</span> <input id="modelTitle" type="text" class="form-control form-control-lg" placeholder="使用者資料維護" required="">
</h6>
</div><!-- /.modal-header -->
<!-- .modal-body -->
<div class="modal-body">
<input type="hidden" id="method"/>
<input type="hidden" id="user_uid"/>
<!-- .form-row -->
<div class="form-row">
<div class="col-md-12">
<div class="form-group">
<label for="cnCountry">帳號類型</label> <select id="user_type" class="custom-select d-block w-100">
<option value="N"> E白板帳號 </option>
<option value="Y"> 自建帳號 </option>
</select>
</div>
</div>
<div class="col-md-12" id="user_elab_div">
<div class="form-group">
<label for="cnCountry">帳號名稱</label> <select id="user_elabName" class="custom-select d-block w-100">
<option value=""> Choose... </option>
</select>
</div>
</div>
<div class="col-md-12" id="user_name_div">
<div class="form-group">
<label for="user_name">使用者名稱</label> <input type="text" id="user_name" class="form-control">
</div>
</div>
<div class="col-md-12" id="user_id_div">
<div class="form-group">
<label for="user_id">使用者帳號</label> <input type="text" id="user_id" class="form-control">
</div>
</div>
<div class="col-md-6" id="user_pwd_div">
<div class="form-group">
<label for="user_pwd">使用者密碼</label> <input type="password" id="user_pwd" class="form-control">
</div>
</div>
<div class="col-md-6" id="user_chkpwd_div">
<div class="form-group">
<label for="user_chkpwd">密碼再確認</label> <input type="password" id="user_chkpwd" class="form-control">
</div>
</div>
<div class="col-md-12" id="user_email_div">
<div class="form-group">
<label for="user_email">使用者Email</label> <input type="email" id="user_email" class="form-control">
</div>
</div>
<div class="col-md-12" id="user_perm_div">
<div class="form-group">
<label for="user_perm">帳號權限</label> <select id="user_perm" class="custom-select d-block w-100">
<option value=""> Choose... </option>
<option value="user"> 一般用戶 </option>
<option value="system"> 管理用戶 </option>
</select>
</div>
</div>
</div><!-- /.form-row -->
</div><!-- /.modal-body -->
<!-- .modal-footer -->
<div class="modal-footer">
<button type="button" id="saveBtn" class="btn btn-primary">儲存</button> <button id="closeBtn" type="button" class="btn btn-light" data-dismiss="modal">關閉</button>
</div><!-- /.modal-footer -->
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</form><!-- /.modal -->

View File

@ -77,7 +77,7 @@
</div><!-- /.form-group --> </div><!-- /.form-group -->
<!-- .form-group --> <!-- .form-group -->
<div class="form-group"> <div class="form-group">
<button class="btn btn-lg btn-primary btn-block" type="submit">登入</button> <button class="btn btn-lg btn-primary btn-block" type="button" id="loginBtn">登入</button>
</div><!-- /.form-group --> </div><!-- /.form-group -->
<!-- .form-group --> <!-- .form-group -->
<div class="form-group text-center"> <div class="form-group text-center">
@ -97,8 +97,13 @@
</main><!-- /.auth --> </main><!-- /.auth -->
<!-- BEGIN BASE JS --> <!-- BEGIN BASE JS -->
<script src="~/assets/vendor/jquery/jquery.min.js"></script> <script src="~/assets/vendor/jquery/jquery.min.js"></script>
<script src="~/assets/vendor/jquery.cookie/jquery.cookie.js"></script>
<script src="~/assets/vendor/sha256/sha256.js"></script>
<script src="~/assets/vendor/popper.js/umd/popper.min.js"></script> <script src="~/assets/vendor/popper.js/umd/popper.min.js"></script>
<script src="~/assets/vendor/bootstrap/js/bootstrap.min.js"></script> <!-- END BASE JS --> <script src="~/assets/vendor/bootstrap/js/bootstrap.min.js"></script>
<script src="~/assets/javascript/custom/globaljs.js"></script>
<script src="~/assets/javascript/custom/login.js?v=1"></script>
<!-- END BASE JS -->
<!-- BEGIN PLUGINS JS --> <!-- BEGIN PLUGINS JS -->
<script src="~/assets/vendor/particles.js/particles.js"></script> <script src="~/assets/vendor/particles.js/particles.js"></script>
<script> <script>

View File

@ -0,0 +1,228 @@
<!DOCTYPE html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- End Required meta tags -->
<!-- Begin SEO tag -->
<title> 奇異KOL資料與成效管理系統 </title>
<meta property="og:title" content="奇異KOL資料與成效管理系統">
<meta name="author" content="詹小弟">
<meta property="og:locale" content="zh_TW">
<meta name="description" content="Responsive admin theme build on top of Bootstrap 4">
<meta property="og:description" content="Responsive admin theme build on top of Bootstrap 4">
<link rel="canonical" href="https://uselooper.com">
<meta property="og:url" content="https://uselooper.com">
<meta property="og:site_name" content="Looper - Bootstrap 4 Admin Theme">
<!-- End SEO tag -->
<!-- FAVICONS -->
<link rel="apple-touch-icon" sizes="144x144" href="~/assets/apple-touch-icon.png">
<link rel="shortcut icon" href="~/assets/favicon.ico">
<meta name="theme-color" content="#3063A0"><!-- End FAVICONS -->
<!-- GOOGLE FONT -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:400,500,600" rel="stylesheet"><!-- End GOOGLE FONT -->
<!-- BEGIN PLUGINS STYLES -->
<link rel="stylesheet" href="~/assets/vendor/open-iconic/font/css/open-iconic-bootstrap.min.css">
<link rel="stylesheet" href="~/assets/vendor/fortawesome/fontawesome-free/css/all.min.css">
<link rel="stylesheet" href="~/assets/vendor/select2/css/select2.min.css">
<link rel="stylesheet" href="~/assets/vendor/tributejs/tribute.css">
<link rel="stylesheet" href="~/assets/vendor/at.js/css/jquery.atwho.min.css">
<link rel="stylesheet" href="~/assets/vendor/bootstrap-select/css/bootstrap-select.min.css">
<link rel="stylesheet" href="~/assets/vendor/flatpickr/flatpickr.min.css">
<link rel="stylesheet" href="~/assets/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css">
<link rel="stylesheet" href="~/assets/vendor/bootstrap-touchspin/jquery.bootstrap-touchspin.min.css">
<link rel="stylesheet" href="~/assets/vendor/nouisliderribute/nouislider.min.css">
<!-- END PLUGINS STYLES -->
<!-- BEGIN THEME STYLES -->
<link rel="stylesheet" href="~/assets/stylesheets/theme.min.css" data-skin="default">
<link rel="stylesheet" href="~/assets/stylesheets/theme-dark.min.css" data-skin="dark">
@RenderSection("Style", required: false)
<link rel="stylesheet" href="~/assets/stylesheets/custom.css">
<script>
var skin = localStorage.getItem('skin') || 'default';
var isCompact = JSON.parse(localStorage.getItem('hasCompactMenu'));
var disabledSkinStylesheet = document.querySelector('link[data-skin]:not([data-skin="' + skin + '"])');
// Disable unused skin immediately
disabledSkinStylesheet.setAttribute('rel', '');
disabledSkinStylesheet.setAttribute('disabled', true);
// add flag class to html immediately
if (isCompact == true) document.querySelector('html').classList.add('preparing-compact-menu');
</script><!-- END THEME STYLES -->
</head>
<body>
<!-- .app -->
<div class="app">
<!--[if lt IE 10]>
<div class="page-message" role="alert">You are using an <strong>outdated</strong> browser. Please <a class="alert-link" href="http://browsehappy.com/">upgrade your browser</a> to improve your experience and security.</div>
<![endif]-->
<!-- .app-header -->
<header class="app-header app-header-dark">
<!-- .top-bar -->
<div class="top-bar">
<!-- .top-bar-brand -->
<div class="top-bar-brand">
<!-- toggle aside menu -->
<button class="hamburger hamburger-squeeze mr-2" type="button" data-toggle="aside-menu" aria-label="toggle aside menu"><span class="hamburger-box"><span class="hamburger-inner"></span></span></button> <!-- /toggle aside menu -->
<a href="index.html">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="28" viewbox="0 0 351 100">
<defs>
<path id="a" d="M156.538 45.644v1.04a6.347 6.347 0 0 1-1.847 3.98L127.708 77.67a6.338 6.338 0 0 1-3.862 1.839h-1.272a6.34 6.34 0 0 1-3.862-1.839L91.728 50.664a6.353 6.353 0 0 1 0-9l9.11-9.117-2.136-2.138a3.171 3.171 0 0 0-4.498 0L80.711 43.913a3.177 3.177 0 0 0-.043 4.453l-.002.003.048.047 24.733 24.754-4.497 4.5a6.339 6.339 0 0 1-3.863 1.84h-1.27a6.337 6.337 0 0 1-3.863-1.84L64.971 50.665a6.353 6.353 0 0 1 0-9l26.983-27.008a6.336 6.336 0 0 1 4.498-1.869c1.626 0 3.252.622 4.498 1.87l26.986 27.006a6.353 6.353 0 0 1 0 9l-9.11 9.117 2.136 2.138a3.171 3.171 0 0 0 4.498 0l13.49-13.504a3.177 3.177 0 0 0 .046-4.453l.002-.002-.047-.048-24.737-24.754 4.498-4.5a6.344 6.344 0 0 1 8.996 0l26.983 27.006a6.347 6.347 0 0 1 1.847 3.98zm-46.707-4.095l-2.362 2.364a3.178 3.178 0 0 0 0 4.501l2.362 2.364 2.361-2.364a3.178 3.178 0 0 0 0-4.501l-2.361-2.364z"></path>
</defs>
<g fill="none" fill-rule="evenodd">
<path fill="currentColor" fill-rule="nonzero" d="M39.252 80.385c-13.817 0-21.06-8.915-21.06-22.955V13.862H.81V.936h33.762V58.1c0 6.797 4.346 9.026 9.026 9.026 2.563 0 5.237-.446 8.58-1.783l3.677 12.034c-5.794 1.894-9.694 3.009-16.603 3.009zM164.213 99.55V23.78h13.372l1.225 5.571h.335c4.457-4.011 10.585-6.908 16.491-6.908 13.817 0 22.174 11.031 22.174 28.08 0 18.943-11.588 29.863-23.957 29.863-4.903 0-9.694-2.117-13.594-6.017h-.446l.78 9.025V99.55h-16.38zm25.852-32.537c6.128 0 10.92-4.903 10.92-16.268 0-9.917-3.232-14.932-10.14-14.932-3.566 0-6.797 1.56-10.252 5.126v22.397c3.12 2.674 6.686 3.677 9.472 3.677zm69.643 13.372c-17.272 0-30.643-10.586-30.643-28.972 0-18.163 13.928-28.971 28.748-28.971 17.049 0 26.075 11.477 26.075 26.52 0 3.008-.558 6.017-.78 7.354h-37.663c1.56 8.023 7.465 11.589 16.491 11.589 5.014 0 9.36-1.337 14.263-3.9l5.46 9.917c-6.351 4.011-14.597 6.463-21.951 6.463zm-1.338-45.463c-6.462 0-11.031 3.454-12.702 10.363h23.622c-.78-6.797-4.568-10.363-10.92-10.363zm44.238 44.126V23.779h13.371l1.337 12.034h.334c5.46-9.025 13.595-13.371 22.398-13.371 4.902 0 7.465.78 10.697 2.228l-3.343 13.706c-3.454-1.003-5.683-1.56-9.806-1.56-6.797 0-13.928 3.566-18.608 13.483v28.749h-16.38z"></path>
<use class="fill-warning" xlink:href="#a"></use>
</g>
</svg>
</a>
</div><!-- /.top-bar-brand -->
<!-- .top-bar-list -->
<div class="top-bar-list">
<!-- .top-bar-item -->
<div class="top-bar-item px-2 d-md-none d-lg-none d-xl-none">
<!-- toggle menu -->
<button class="hamburger hamburger-squeeze" type="button" data-toggle="aside" aria-label="toggle menu"><span class="hamburger-box"><span class="hamburger-inner"></span></span></button> <!-- /toggle menu -->
</div><!-- /.top-bar-item -->
<!-- .top-bar-item -->
<div class="top-bar-item top-bar-item-right px-0">
<!-- .btn-account -->
<div class="dropdown d-none d-sm-flex">
<button class="btn-account" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="user-avatar user-avatar-md"><img src="~/assets/images/avatars/unknown-profile.jpg" alt=""></span> <span class="account-summary pr-lg-4 d-none d-lg-block"><span class="account-name">@ViewData["user_name"]</span> <span class="account-description">@ViewData["user_permtype"]</span></span></button> <!-- .dropdown-menu -->
<div class="dropdown-menu">
<div class="dropdown-arrow d-lg-none" x-arrow=""></div>
<div class="dropdown-arrow ml-3 d-none d-lg-block"></div>
<h6 class="dropdown-header d-none d-sm-block d-lg-none"> Beni Arisandi </h6><a class="dropdown-item" href="user-profile.html"><span class="dropdown-icon oi oi-person"></span> Profile</a> <a class="dropdown-item" href="auth-signin-v1.html"><span class="dropdown-icon oi oi-account-logout"></span> Logout</a>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#">Help Center</a> <a class="dropdown-item" href="#">Ask Forum</a> <a class="dropdown-item" href="#">Keyboard Shortcuts</a>
</div><!-- /.dropdown-menu -->
</div><!-- /.btn-account -->
</div><!-- /.top-bar-item -->
</div><!-- /.top-bar-list -->
</div><!-- /.top-bar -->
</header><!-- /.app-header -->
<!-- .app-aside -->
<aside class="app-aside app-aside-expand-md app-aside-light">
<!-- .aside-content -->
<div class="aside-content">
<!-- .aside-header -->
<header class="aside-header d-block d-md-none">
<!-- .btn-account -->
<button class="btn-account" type="button" data-toggle="collapse" data-target="#dropdown-aside"><span class="user-avatar user-avatar-lg"><img src="~/assets/images/avatars/unknown-profile.jpg" alt=""></span> <span class="account-icon"><span class="fa fa-caret-down fa-lg"></span></span> <span class="account-summary"><span class="account-name">@ViewData["user_name"]</span> <span class="account-description">@ViewData["user_permtype"]</span></span></button> <!-- /.btn-account -->
<!-- .dropdown-aside -->
<div id="dropdown-aside" class="dropdown-aside collapse">
<!-- dropdown-items -->
<div class="pb-3">
<a class="dropdown-item" href="user-profile.html"><span class="dropdown-icon oi oi-person"></span> Profile</a> <a class="dropdown-item" href="auth-signin-v1.html"><span class="dropdown-icon oi oi-account-logout"></span> Logout</a>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#">Help Center</a> <a class="dropdown-item" href="#">Ask Forum</a> <a class="dropdown-item" href="#">Keyboard Shortcuts</a>
</div><!-- /dropdown-items -->
</div><!-- /.dropdown-aside -->
</header><!-- /.aside-header -->
<!-- .aside-menu -->
<div class="aside-menu overflow-hidden">
<!-- .stacked-menu -->
<nav id="stacked-menu" class="stacked-menu">
<!-- .menu -->
<ul class="menu">
<!-- .menu-item -->
<li class="menu-item">
<a href="~/" class="menu-link"><span class="menu-icon fas fa-home"></span> <span class="menu-text">Dashboard</span></a>
</li><!-- /.menu-item -->
<!-- .menu-item -->
<li class="menu-item has-child" id="authMenu" style='@ViewData["authMenu"]'>
<a href="#" class="menu-link"><span class="menu-icon oi oi-wrench"></span> <span class="menu-text">Auth</span></a> <!-- child menu -->
<ul class="menu">
<li class="menu-item">
<a href="auth-comingsoon-v1.html" class="menu-link">使用者管理</a>
</li>
</ul><!-- /child menu -->
</li><!-- /.menu-item -->
</ul><!-- /.menu -->
</nav><!-- /.stacked-menu -->
</div><!-- /.aside-menu -->
<!-- Skin changer -->
<footer class="aside-footer border-top p-2">
<button class="btn btn-light btn-block text-primary" data-toggle="skin"><span class="d-compact-menu-none">Night mode</span> <i class="fas fa-moon ml-1"></i></button>
</footer><!-- /Skin changer -->
</div><!-- /.aside-content -->
</aside><!-- /.app-aside -->
<!-- .app-main -->
<main class="app-main">
<!-- .wrapper -->
<div class="wrapper">
<!-- .page -->
<div class="page">
@RenderBody()
</div><!-- /.page -->
</div><!-- /.wrapper -->
<!-- .app-footer -->
<footer class="app-footer" style="display:none;">
<ul class="list-inline">
<li class="list-inline-item">
<a class="text-muted" href="#">Support</a>
</li>
<li class="list-inline-item">
<a class="text-muted" href="#">Help Center</a>
</li>
<li class="list-inline-item">
<a class="text-muted" href="#">Privacy</a>
</li>
<li class="list-inline-item">
<a class="text-muted" href="#">Terms of Service</a>
</li>
</ul>
<div class="copyright"> Copyright © 2023. All right reserved. </div>
</footer><!-- /.app-footer -->
</main><!-- /.app-main -->
</div><!-- /.app -->
<!-- BEGIN BASE JS -->
<script src="~/assets/vendor/jquery/jquery.min.js"></script>
<script src="~/assets/vendor/jquery.cookie/jquery.cookie.js"></script>
<script src="~/assets/javascript/custom/globaljs.js"></script>
<script src="~/assets/vendor/popper.js/umd/popper.min.js"></script>
<script src="~/assets/vendor/bootstrap/js/bootstrap.min.js"></script> <!-- END BASE JS -->
<!-- BEGIN PLUGINS JS -->
<script src="~/assets/vendor/pace-progress/pace.min.js"></script>
<script src="~/assets/vendor/stacked-menu/js/stacked-menu.min.js"></script>
<script src="~/assets/vendor/perfect-scrollbar/perfect-scrollbar.min.js"></script>
<script src="~/assets/vendor/bootstrap-select/js/bootstrap-select.min.js"></script>
<script src="~/assets/vendor/masonry-layout/masonry.pkgd.min.js"></script>
<script src="~/assets/vendor/flatpickr/flatpickr.min.js"></script>
<script src="~/assets/vendor/flatpickr/plugins/monthSelect/index.js"></script>
<script src="~/assets/vendor/wnumb/wNumb.min.js"></script>
<script src="~/assets/vendor/nouisliderribute/nouislider.min.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/vendor/jquery.ui.widget.js"></script>
<script src="~/assets/vendor/blueimp-load-image/js/load-image.all.min.js"></script>
<script src="~/assets/vendor/blueimp-canvas-to-blob/js/canvas-to-blob.min.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.iframe-transport.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload-process.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload-image.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload-audio.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload-video.js"></script>
<script src="~/assets/vendor/blueimp-file-upload/js/jquery.fileupload-validate.js"></script>
<script src="~/assets/vendor/bootstrap-touchspin/jquery.bootstrap-touchspin.min.js"></script>
<script src="~/assets/vendor/easy-pie-chart/jquery.easypiechart.min.js"></script>
<script src="~/assets/vendor/chart.js/Chart.min.js"></script>
<script src="~/assets/vendor/sha256/sha256.js"></script>
<!-- END PLUGINS JS -->
<!-- BEGIN SELECT2-->
<script src="~/assets/vendor/handlebars/handlebars.min.js"></script>
<script src="~/assets/vendor/typeahead.js/typeahead.bundle.min.js"></script>
<script src="~/assets/vendor/select2/js/select2.min.js"></script>
<script src="~/assets/vendor/tributejs/tribute.min.js"></script>
<script src="~/assets/vendor/jquery.caret/jquery.caret.min.js"></script>
<script src="~/assets/vendor/at.js/js/jquery.atwho.min.js"></script>
<script src="~/assets/vendor/zxcvbn/zxcvbn.js"></script>
<script src="~/assets/vendor/vanilla-text-mask/vanillaTextMask.js"></script>
<script src="~/assets/vendor/text-mask-addons/textMaskAddons.js"></script>
<!-- END SELECT2-->
<!-- BEGIN THEME JS -->
<script src="~/assets/javascript/theme.min.js"></script> <!-- END THEME JS -->
<!-- BEGIN PAGE LEVEL JS -->
@RenderSection("Script", required: false)
<!-- END PAGE LEVEL JS -->
</body>
</html>

View File

@ -7,8 +7,8 @@
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"SQLConnectionString": "Data Source=mssql.bremen.com.tw;Initial Catalog=journeys_wanthome;User ID=journeys_wanthome;Password=2icR52n@9;Max Pool Size=100;", "SQLConnectionString": "Data Source=sql.bremen.com.tw;Initial Catalog=journeys_wanthome;User ID=journeys_wanthome;Password=2icR52n@9;Max Pool Size=100;",
"ElabConnectionString": "Data Source=mssql.bremen.com.tw;Initial Catalog=elab;User ID=elab;Password=2#2k9Vfg" "ElabConnectionString": "Data Source=sql.bremen.com.tw;database=elab;uid=elab;pwd=2#2k9Vfg"
}, },
"Admin": { "Admin": {
"uid": "system", "uid": "system",

View File

@ -0,0 +1,5 @@

$(document).ready(function () {
});

View File

@ -0,0 +1,258 @@
(function ($, document) {
(function ($) {
$.UrlParam = function (name) {
//宣告正規表達式
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
/*
* window.location.search 獲取URL ?之後的參數(包含問號)
* substr(1) 獲取第一個字以後的字串(就是去除掉?)
* match(reg) 用正規表達式檢查是否符合要查詢的參數
*/
var r = window.location.search.substr(1).match(reg);
//如果取出的參數存在則取出參數的值否則回穿null
if (r != null) return unescape(r[2]); return null;
}
})(jQuery);
if ($.cookie) {
$.cookieKey = function (CookieName, KeyName, Value, Options) {
var reg = new RegExp("(?:([^=]+)=([^&]*)&?)", "ig"),
match = null,
matches = [];
var cookieVal = $.cookie(CookieName);
while (match = reg.exec(cookieVal)) {
if (KeyName.toLowerCase() == match[1].toLowerCase()) {
if (Value) { //we are updating, collect all values
matches.push([match[1], Value]);
}
else {
return match[2]; //we are getting, sub key found just return it
}
}
else if (Value) { //we are updating, collect all values
matches.push([match[1], match[2]]);
}
}
if (Value) { //we are updating, update values
updatedValue = "",
sep = "";
for (i = 0; i < matches; i++) {
updatedValue += sep + matches[i][0] + "=" + matches[i][1];
sep = "&"
}
$.cookie(CookieName, updatedValue, Options);
}
else return null;//we are getting, value not found
}
}
})(jQuery, document);
// 對Date的擴充套件將 Date 轉化為指定格式的String
// 月(M)、日(d)、小時(h)、分(m)、秒(s)、季度(q) 可以用 1-2 個佔位符,
// 年(y)可以用 1-4 個佔位符,毫秒(S)只能用 1 個佔位符(是 1-3 位的數字)
// 例子:
// (new Date()).format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).format("yyyy-M-d hⓜs.S") ==> 2006-7-2 8:9:4.18
Date.prototype.format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小時
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
Date.prototype.addSeconds = function (seconds) {
this.setSeconds(this.getSeconds() + seconds);
return this;
}
Date.prototype.addMinutes = function (minutes) {
this.setMinutes(this.getMinutes() + minutes);
return this;
}
Date.prototype.addHours = function (hours) {
this.setHours(this.getHours() + hours);
return this;
}
Date.prototype.addDays = function (days) {
this.setDate(this.getDate() + days);
return this;
}
Date.prototype.addMonths = function (months) {
this.setMonth(this.getMonth() + months);
return this;
}
Date.prototype.addYears = function (years) {
this.setFullYear(this.getFullYear() + years);
return this;
}
function diffSeconds(milliseconds) {
return Math.floor(milliseconds / 1000);
}
function diffMinutes(milliseconds) {
return Math.floor(milliseconds / 1000 / 60);
}
function diffHours(milliseconds) {
return Math.floor(milliseconds / 1000 / 60 / 60);
}
function diffDays(milliseconds) {
return Math.floor(milliseconds / 1000 / 60 / 60 / 24);
}
function padding(num, length) {
for (var len = (num + "").length; len < length; len = num.length) {
num = "0" + num;
}
return num;
}
function clearChildren(element) {
for (var i = 0; i < element.childNodes.length; i++) {
var e = element.childNodes[i];
if (e.tagName) switch (e.tagName.toLowerCase()) {
case 'input':
switch (e.type) {
case "radio":
case "checkbox": break;
case "button":
case "submit":
case "text": e.value = ''; break;
case "image": break;
default: if (e.type != "checkbox") { e.value = ''; }; break;
}
break;
case 'select': e.selectedIndex = 0; break;
case 'textarea': e.innerHTML = ''; break;
default: clearChildren(e);
}
}
$(element).children().find('textarea').each(function () {
$(this).val('');
});
$(element).children().find('select').each(function () {
$(this).prop('selectedIndex', 0);
});
}
$(document).ready(function () {
$('.modal').on("hidden.bs.modal", function (e) {
clearChildren(this);
if ($('.modal:visible').length) {
$('.modal-backdrop').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) - 10);
$('body').addClass('modal-open');
}
}).on("show.bs.modal", function (e) {
if ($('.modal:visible').length) {
$('.modal-backdrop.in').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) + 10);
$(this).css('z-index', parseInt($('.modal-backdrop.in').first().css('z-index')) + 10);
}
});
(function ($) {
$.UrlParam = function (name) {
//宣告正規表達式
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
/*
* window.location.search 獲取URL ?之後的參數(包含問號)
* substr(1) 獲取第一個字以後的字串(就是去除掉?)
* match(reg) 用正規表達式檢查是否符合要查詢的參數
*/
var r = window.location.search.substr(1).match(reg);
//如果取出的參數存在則取出參數的值否則回穿null
if (r != null) return unescape(r[2]); return null;
}
})(jQuery);
});
String.prototype.isDate = function () {
var p;
var re1 = /(\d{4})[年./-](\d{1,2})[月./-](\d{1,2})[日]?$/;
var re2 = /(\d{1,2})[月./-](\d{1,2})[日./-](\d{2})[年]?$/;
var re3 = /(\d{1,2})[月./-](\d{1,2})[日./-](\d{4})[年]?$/;
if (re1.test(this)) {
p = re1.exec(this);
return new Date(p[1], p[2], p[3]);
}
if (re2.test(this)) {
p = re2.exec(this);
return new Date(p[3], p[1], p[2]);
}
if (re3.test(this)) {
p = re3.exec(this);
return new Date(p[3], p[1], p[2]);
}
return "";
}
String.prototype.isDigit = function () {
var s = this.Trim();
return (s.replace(/\d/g, "").length == 0);
}
/*** 檢查是否由數字字母和下劃線組成 ***/
String.prototype.isAlpha = function () {
return (this.replace(/\w/g, "").length == 0);
}
/*** 檢查是否為數 ***/
String.prototype.isNumber = function () {
var s = this.Trim();
return (s.search(/^[+-]?[0-9.]*$/) >= 0);
}
/*** 返回字節數 ***/
String.prototype.lenb = function () {
return this.replace(/[^\x00-\xff]/g, "**").length;
}
/*** 檢查是否包含漢字 ***/
String.prototype.isInChinese = function () {
return (this.length != this.replace(/[^\x00-\xff]/g, "**").length);
}
/*** 刪除首尾空格 ***/
String.prototype.Trim = function () {
return this.replace(/(^\s*)|(\s*$)/g, "");
}
const apiUrl = '' /*** 有值的話需要斜線結尾喔 **/
/*** 簡單的email檢查 ***/
String.prototype.isEmail = function () {
var strr;
var mail = this;
var re = /(\w+@\w+\.\w+)(\.{0,1}\w*)(\.{0,1}\w*)/i;
re.exec(mail);
if (RegExp.$3 != "" && RegExp.$3 != "." && RegExp.$2 != ".")
strr = RegExp.$1 + RegExp.$2 + RegExp.$3;
else
if (RegExp.$2 != "" && RegExp.$2 != ".")
strr = RegExp.$1 + RegExp.$2;
else
strr = RegExp.$1;
return (strr == mail);
}

View File

@ -0,0 +1,63 @@
$(document).ready(function () {
if ($.UrlParam("isLogout") != "true") {
if ($.cookie("token_key") != null) {
if ($.cookie("token_key") != "") {
location.href = "../";
alert("has token_key value :" + $.cookie("token_key"));
}
}
}
$("#loginBtn").click(function () {
var id = $("#inputUser").val();
var pwd = $("#inputPassword").val();
var remember = "N";
if ($("#remember-me").prop("checked")) {
remember = "Y";
}
var err_msg = "";
if (id === "") {
err_msg += "請輸入帳號!\n";
}
if (pwd === "") {
err_msg += "請輸入密碼!\n";
}
if (err_msg !== "") {
alert(err_msg);
return;
}
pwd = sha256_digest(pwd);
var formData = {
id: id,
pwd: pwd,
remember: remember
}
$.ajax({
url: "/AuthApi/signin",
type: "POST",
data: formData,
success: function (data, textStatus, jqXHR) {
if (data.ret == "yes") {
location.href = "/Home/Dashboard";
//location.href = "/BackEnd/nounsList";
} else {
alert(data.message);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('網路或伺服器發生錯誤,請稍後重試!');
}
});
});
});

View File

@ -0,0 +1,391 @@
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
// DataTables Demo
// =============================================================
var DataTablesResponsive = /*#__PURE__*/function () {
function DataTablesResponsive() {
_classCallCheck(this, DataTablesResponsive);
this.init();
}
_createClass(DataTablesResponsive, [{
key: "init",
value: function init() {
// event handlers
this.table = this.table();
}
}, {
key: "table",
value: function table() {
$('#dt-responsive').DataTable({
ajax: {
url: '/AuthApi/userList',
type: 'POST',
dataSrc: 'userList'
},
rowId: 'user_uid',
responsive: true,
dom: "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>\n <'table-responsive'tr>\n <'row align-items-center'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7 d-flex justify-content-end'p>>",
language: {
paginate: {
previous: '<i class="fa fa-lg fa-angle-left"></i>',
next: '<i class="fa fa-lg fa-angle-right"></i>'
}
},
columns: [{
data: 'user_name'
}, {
data: 'user_id'
}, {
data: 'user_type'
}, {
data: 'user_perm'
}, {
data: 'user_lastlogintime'
}, {
data: 'user_uid'
}],
columnDefs: [
{
targets: 2,
orderable: false,
searchable: false,
render: function render(data, type, row, meta) {
if (row.user_type == 'N') {
return 'E白板帳號';
} else {
return '自建帳號';
}
}
},
{
targets: 3,
orderable: false,
searchable: false,
render: function render(data, type, row, meta) {
if (row.user_perm == 'user') {
return '一般使用者';
} else {
return '系統使用者';
}
}
}, {
targets: 5,
orderable: false,
searchable: false,
render: function render(data, type, row, meta) {
return "<a class=\"btn btn-sm btn-icon btn-secondary\" data-method=\"edit\" href=\"javascript: void(0);\" data-uid=\"".concat(row.user_uid, "\"><i class=\"fa fa-pencil-alt\"></i></a>\n <a class=\"btn btn-sm btn-icon btn-secondary\" data-method=\"del\" href=\"javascript: void(0);\" data-uid=\"").concat(row.user_uid, "\"><i class=\"far fa-trash-alt\"></i></a>");
}
}
],
initComplete: function () {
userTable = $('#dt-responsive').dataTable();
$('#dt-responsive').on('click', 'a', function () {
buttonClick(this);
});
$('#dt-responsive').on('click', 'input[name="selectedRow[]"]', function () {
checkboxClick(this);
});
}
});
}
}]);
return DataTablesResponsive;
}();
/**
* Keep in mind that your scripts may not always be executed after the theme is completely ready,
* you might need to observe the `theme:load` event to make sure your scripts are executed after the theme is ready.
*/
var userTable;
var userRowID;
var userRowPos;
$(document).on('theme:init', function () {
new DataTablesResponsive();
});
function buttonClick(obj) {
var type = obj.getAttribute('data-method');
var uid = obj.getAttribute('data-uid');
userRowID = $('#' + uid);
userRowPos = userTable.fnGetPosition($('#' + uid)[0]);
if (type == "edit") {
var formData = {
method: 'get',
user_uid: uid
}
$.ajax({
url: "/AuthApi/addEditGetUser",
type: "post",
data: formData,
success: function (data, textStatus, jqXHR) {
if (data.ret == "yes") {
var obj = data.user;
$("#method").val('edit');
$("#user_uid").val(obj.user_uid);
$("#user_type").val(obj.user_type).trigger('change');
$("#user_perm").val(obj.user_perm).trigger('change');
if (obj.user_type == "N") {
$("#user_elabName").val(obj.user_id).trigger('change');
} else {
$("#user_name").val(obj.user_name).trigger('change');
$("#user_id").val(obj.user_id).trigger('change');
$("#user_email").val(obj.user_email).trigger('change');
}
modalStatus("Y");
$('#clientNewModal').modal('toggle');
} else {
alert(data.message);
if (data.err_code == "99999") {
location.href = "/Root/Login";
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('網路或伺服器發生錯誤,請稍後重試!');
}
});
}
if (type == "del") {
if (confirm('確定刪除此筆資料?')) {
var formData = {
method: 'del',
user_uid: uid
}
$.ajax({
url: "/AuthApi/addEditGetUser",
type: "post",
data: formData,
success: function (data, textStatus, jqXHR) {
if (data.ret == "yes") {
var row = userTable.api().row(userRowID).remove().draw(false);
alert('刪除成功');
} else {
alert(data.message);
if (data.err_code == "99999") {
location.href = "/Root/Login";
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('網路或伺服器發生錯誤,請稍後重試!');
}
});
}
}
}
function modalStatus(readonly) {
if (readonly == "Y") {
$("#user_type").prop("disabled", true);
$("#user_elabName").prop("disabled", true);
$("#user_id").prop("readonly", true);
} else {
$("#user_type").prop("disabled", false);
$("#user_elabName").prop("disabled", false);
$("#user_id").prop("readonly", false);
}
}
$(document).ready(function () {
loadElabList();
userTypeStatus();
$("#saveBtn").on('click', function () {
var user_uid = $("#user_uid").val();
var user_type = $("#user_type").val();
var method = $("#method").val();
var user_id = $("#user_id").val();
var user_elabName = $("#user_elabName").val();
var user_name = $("#user_name").val();
var user_pwd = $("#user_pwd").val();
var user_chkpwd = $("#user_chkpwd").val();
var user_email = $("#user_email").val();
var user_perm = $("#user_perm").val();
var err_msg = "";
if (user_type == "N") {
if ($("#user_elabName").val() == "") {
err_msg += "請選擇要加入系統用戶的E白板帳號!\n";
}
} else {
if (user_id == "") {
err_msg += "請輸入帳號!\n";
}
if (user_name == "") {
err_msg += "請輸入使用者名稱!\n";
}
if (user_email.isEmail == false) {
err_msg += "請輸入正確的Email!\n";
}
if (method == "add") {
if (user_pwd == "") {
err_msg += "請輸入密碼!\n";
}
}
if (user_pwd != user_chkpwd) {
err_msg += "請確認兩次密碼是否輸入正確!\n";
}
if (method == "edit" && user_pwd == "") {
user_pwd = "";
} else {
user_pwd = sha256_digest(user_pwd);
}
}
if (user_perm == "") {
err_msg += "請選擇此使用者的使用權限!\n";
}
if (err_msg != "") {
alert(err_msg);
return;
}
var formData = {
user_uid: user_uid,
user_type: user_type,
method: method,
user_id: user_id,
user_elabName: user_elabName,
user_name: user_name,
user_email: user_email,
user_pwd: user_pwd,
user_perm: user_perm
}
$.ajax({
url: "/AuthApi/AddEditGetUser",
type: "post",
data: formData,
success: function (data, textStatus, jqXHR) {
if (data.ret == "yes") {
var obj = data.user;
if (method == "add") {
userTable.fnAddData(obj);
alert("新增完成");
}
if (method == "edit") {
userTable.fnUpdate(obj, userRowPos);
alert("修改完成");
}
$('#clientNewModal').modal('toggle');
} else {
alert(data.message);
if (data.err_code == "99999") {
location.href = "/Root/Login";
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('網路或伺服器發生錯誤,請稍後重試!');
}
});
});
$("#user_type").on('change', function () {
userTypeStatus();
});
$('#userNewModal').on('click', function () {
$('#method').val('add');
modalStatus("N");
$('#clientNewModal').modal('toggle');
});
function userTypeStatus() {
var user_type = $("#user_type").val();
if (user_type == "Y") {
$("#user_elab_div").hide();
$("#user_name_div").show();
$("#user_id_div").show();
$("#user_pwd_div").show();
$("#user_chkpwd_div").show();
$("#user_email_div").show();
} else {
$("#user_elab_div").show();
$("#user_name_div").hide();
$("#user_id_div").hide();
$("#user_pwd_div").hide();
$("#user_chkpwd_div").hide();
$("#user_email_div").hide();
}
}
function loadElabList() {
$("#user_elabName")
.find("option")
.remove()
.end()
.append("<option value=\"\"> Choose... </option>");
$.ajax({
url: "/AuthApi/elab_UserList",
type: "post",
data: {},
success: function (data, textStatus, jqXHR) {
if (data.ret == "yes") {
$.each(data.userList, function (i, item) {
$("#user_elabName").append($("<option>", {
value: item.userid,
text: item.username + " (" + item.mail +")"
}));
});
} else {
alert(data.message);
if (data.err_code == "99999") {
location.href = "/Root/Login";
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('網路或伺服器發生錯誤,請稍後重試!');
}
});
}
});

View File

@ -0,0 +1,117 @@
/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (value !== undefined && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) === undefined) {
return false;
}
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));

250
wwwroot/assets/vendor/sha256/sha256.js vendored Normal file
View File

@ -0,0 +1,250 @@
/*
* A JavaScript implementation of the SHA256 hash function.
*
* FILE: sha256.js
* VERSION: 0.8
* AUTHOR: Christoph Bichlmeier <informatik@zombiearena.de>
*
* NOTE: This version is not tested thoroughly!
*
* Copyright (c) 2003, Christoph Bichlmeier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* ======================================================================
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* SHA256 logical functions */
function rotateRight(n,x) {
return ((x >>> n) | (x << (32 - n)));
}
function choice(x,y,z) {
return ((x & y) ^ (~x & z));
}
function majority(x,y,z) {
return ((x & y) ^ (x & z) ^ (y & z));
}
function sha256_Sigma0(x) {
return (rotateRight(2, x) ^ rotateRight(13, x) ^ rotateRight(22, x));
}
function sha256_Sigma1(x) {
return (rotateRight(6, x) ^ rotateRight(11, x) ^ rotateRight(25, x));
}
function sha256_sigma0(x) {
return (rotateRight(7, x) ^ rotateRight(18, x) ^ (x >>> 3));
}
function sha256_sigma1(x) {
return (rotateRight(17, x) ^ rotateRight(19, x) ^ (x >>> 10));
}
function sha256_expand(W, j) {
return (W[j&0x0f] += sha256_sigma1(W[(j+14)&0x0f]) + W[(j+9)&0x0f] +
sha256_sigma0(W[(j+1)&0x0f]));
}
/* Hash constant words K: */
var K256 = new Array(
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);
/* global arrays */
var ihash, count, buffer;
var sha256_hex_digits = "0123456789abcdef";
/* Add 32-bit integers with 16-bit operations (bug in some JS-interpreters:
overflow) */
function safe_add(x, y)
{
var lsw = (x & 0xffff) + (y & 0xffff);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xffff);
}
/* Initialise the SHA256 computation */
function sha256_init() {
ihash = new Array(8);
count = new Array(2);
buffer = new Array(64);
count[0] = count[1] = 0;
ihash[0] = 0x6a09e667;
ihash[1] = 0xbb67ae85;
ihash[2] = 0x3c6ef372;
ihash[3] = 0xa54ff53a;
ihash[4] = 0x510e527f;
ihash[5] = 0x9b05688c;
ihash[6] = 0x1f83d9ab;
ihash[7] = 0x5be0cd19;
}
/* Transform a 512-bit message block */
function sha256_transform() {
var a, b, c, d, e, f, g, h, T1, T2;
var W = new Array(16);
/* Initialize registers with the previous intermediate value */
a = ihash[0];
b = ihash[1];
c = ihash[2];
d = ihash[3];
e = ihash[4];
f = ihash[5];
g = ihash[6];
h = ihash[7];
/* make 32-bit words */
for(var i=0; i<16; i++)
W[i] = ((buffer[(i<<2)+3]) | (buffer[(i<<2)+2] << 8) | (buffer[(i<<2)+1]
<< 16) | (buffer[i<<2] << 24));
for(var j=0; j<64; j++) {
T1 = h + sha256_Sigma1(e) + choice(e, f, g) + K256[j];
if(j < 16) T1 += W[j];
else T1 += sha256_expand(W, j);
T2 = sha256_Sigma0(a) + majority(a, b, c);
h = g;
g = f;
f = e;
e = safe_add(d, T1);
d = c;
c = b;
b = a;
a = safe_add(T1, T2);
}
/* Compute the current intermediate hash value */
ihash[0] += a;
ihash[1] += b;
ihash[2] += c;
ihash[3] += d;
ihash[4] += e;
ihash[5] += f;
ihash[6] += g;
ihash[7] += h;
}
/* Read the next chunk of data and update the SHA256 computation */
function sha256_update(data, inputLen) {
var i, index, curpos = 0;
/* Compute number of bytes mod 64 */
index = ((count[0] >> 3) & 0x3f);
var remainder = (inputLen & 0x3f);
/* Update number of bits */
if ((count[0] += (inputLen << 3)) < (inputLen << 3)) count[1]++;
count[1] += (inputLen >> 29);
/* Transform as many times as possible */
for(i=0; i+63<inputLen; i+=64) {
for(var j=index; j<64; j++)
buffer[j] = data.charCodeAt(curpos++);
sha256_transform();
index = 0;
}
/* Buffer remaining input */
for(var j=0; j<remainder; j++)
buffer[j] = data.charCodeAt(curpos++);
}
/* Finish the computation by operations such as padding */
function sha256_final() {
var index = ((count[0] >> 3) & 0x3f);
buffer[index++] = 0x80;
if(index <= 56) {
for(var i=index; i<56; i++)
buffer[i] = 0;
} else {
for(var i=index; i<64; i++)
buffer[i] = 0;
sha256_transform();
for(var i=0; i<56; i++)
buffer[i] = 0;
}
buffer[56] = (count[1] >>> 24) & 0xff;
buffer[57] = (count[1] >>> 16) & 0xff;
buffer[58] = (count[1] >>> 8) & 0xff;
buffer[59] = count[1] & 0xff;
buffer[60] = (count[0] >>> 24) & 0xff;
buffer[61] = (count[0] >>> 16) & 0xff;
buffer[62] = (count[0] >>> 8) & 0xff;
buffer[63] = count[0] & 0xff;
sha256_transform();
}
/* Split the internal hash values into an array of bytes */
function sha256_encode_bytes() {
var j=0;
var output = new Array(32);
for(var i=0; i<8; i++) {
output[j++] = ((ihash[i] >>> 24) & 0xff);
output[j++] = ((ihash[i] >>> 16) & 0xff);
output[j++] = ((ihash[i] >>> 8) & 0xff);
output[j++] = (ihash[i] & 0xff);
}
return output;
}
/* Get the internal hash as a hex string */
function sha256_encode_hex() {
var output = new String();
for(var i=0; i<8; i++) {
for(var j=28; j>=0; j-=4)
output += sha256_hex_digits.charAt((ihash[i] >>> j) & 0x0f);
}
return output;
}
/* Main function: returns a hex string representing the SHA256 value of the
given data */
function sha256_digest(data) {
sha256_init();
sha256_update(data, data.length);
sha256_final();
return sha256_encode_hex();
}
/* test if the JS-interpreter is working properly */
function sha256_self_test()
{
return sha256_digest("message digest") ==
"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650";
}