Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
T
TokenVaultManagement
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jasonwai
TokenVaultManagement
Commits
e1cd39b5
Commit
e1cd39b5
authored
Jun 09, 2023
by
Jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加了權限
parent
095fd6e0
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
901 additions
and
371 deletions
+901
-371
HomeController.cs
... Vault Management/backstage/Controllers/HomeController.cs
+15
-7
TokenVaultController .cs
...Management/backstage/Controllers/TokenVaultController .cs
+11
-4
UserController.cs
... Vault Management/backstage/Controllers/UserController.cs
+432
-134
User.cs
...ant Token Vault Management/backstage/Models/Users/User.cs
+1
-0
Startup.cs
Merchant Token Vault Management/backstage/Startup.cs
+19
-3
Index.cshtml
... Token Vault Management/backstage/Views/Home/Index.cshtml
+32
-83
_Layout.cshtml
...en Vault Management/backstage/Views/Shared/_Layout.cshtml
+5
-5
List.cshtml
...n Vault Management/backstage/Views/TokenVault/List.cshtml
+8
-5
ListFields.cshtml
...t Management/backstage/Views/TokenVault/ListFields.cshtml
+8
-5
ListMasks.cshtml
...lt Management/backstage/Views/TokenVault/ListMasks.cshtml
+32
-9
ListUsers.cshtml
...lt Management/backstage/Views/TokenVault/ListUsers.cshtml
+37
-32
ChangePassword.cshtml
...ult Management/backstage/Views/User/ChangePassword.cshtml
+127
-0
GetUser.cshtml
...oken Vault Management/backstage/Views/User/GetUser.cshtml
+56
-24
ListDepartments.cshtml
...lt Management/backstage/Views/User/ListDepartments.cshtml
+16
-12
ListUsers.cshtml
...en Vault Management/backstage/Views/User/ListUsers.cshtml
+78
-46
Login.cshtml
... Token Vault Management/backstage/Views/User/Login.cshtml
+11
-2
style.css
...nt Token Vault Management/backstage/wwwroot/css/style.css
+13
-0
No files found.
Merchant Token Vault Management/backstage/Controllers/HomeController.cs
View file @
e1cd39b5
...
...
@@ -14,7 +14,7 @@ using System.Net.Http;
namespace
backstage.Controllers
{
//[Authorize]
public
class
HomeController
:
Controller
...
...
@@ -39,23 +39,31 @@ namespace backstage.Controllers
public
async
Task
<
IActionResult
>
Index
()
{
ResultModel
result
=
new
ResultModel
();
return
View
();
}
public
IActionResult
Error
()
{
return
View
();
}
public
IActionResult
AccessDenied
()
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"您沒有訪問此頁面的權限。"
;
return
RedirectToAction
(
"Index"
);
}
}
...
...
Merchant Token Vault Management/backstage/Controllers/TokenVaultController .cs
View file @
e1cd39b5
...
...
@@ -255,7 +255,7 @@ namespace backstage.Controllers
return
View
();
}
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
IActionResult
>
AddUsers
([
FromBody
]
JsonElement
requestData
)
{
...
...
@@ -591,6 +591,7 @@ namespace backstage.Controllers
}
//新增欄位
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
IActionResult
>
CreateField
(
FieldForCreate
FieldForCreate
)
{
...
...
@@ -696,6 +697,7 @@ namespace backstage.Controllers
//新增MASK ajax
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
ResultModel
>
CreateMask
(
IFormCollection
form
)
{
...
...
@@ -793,7 +795,9 @@ namespace backstage.Controllers
//return View();
}
//刪除MASK ajx
//刪除MASK ajax
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
ResultModel
>
DeleteMask
(
IFormCollection
form
)
{
...
...
@@ -893,6 +897,7 @@ namespace backstage.Controllers
//編輯MASK ajax
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
ResultModel
>
EditMask
(
IFormCollection
form
)
{
...
...
@@ -1114,6 +1119,7 @@ namespace backstage.Controllers
}
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpGet
]
public
async
Task
<
IActionResult
>
CreateTokenVault
()
{
...
...
@@ -1150,9 +1156,9 @@ namespace backstage.Controllers
return
View
();
}
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpGet
(
"/TokenVault/Edit/{id}"
)]
public
async
Task
<
IActionResult
>
Edit
(
int
id
,
[
FromQuery
]
int
merchantid
)
public
async
Task
<
IActionResult
>
Edit
(
int
id
,
[
FromQuery
]
int
merchantid
)
{
#
region
取得部門列表
var
DepartmentsResponse
=
new
DepartmentsResponse
();
...
...
@@ -1217,6 +1223,7 @@ namespace backstage.Controllers
return
View
();
}
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
IActionResult
>
CreateTokenVault
(
TokenVaultForCreate
tokenVault
)
{
...
...
Merchant Token Vault Management/backstage/Controllers/UserController.cs
View file @
e1cd39b5
...
...
@@ -21,7 +21,7 @@ using TokenVault_management.Models;
namespace
backstage.Controllers
{
public
class
UserController
:
Controller
{
private
readonly
IHttpContextAccessor
_httpContextAccessor
;
...
...
@@ -40,23 +40,198 @@ namespace backstage.Controllers
_httpContextAccessor
=
httpContextAccessor
;
}
[
HttpGet
]
public
async
Task
<
IActionResult
>
Login
()
{
return
View
();
}
[
HttpPost
]
[
ValidateAntiForgeryToken
]
public
async
Task
<
IActionResult
>
Login
(
User
user
,
string
returnUrl
)
{
if
(!
ModelState
.
IsValid
)
{
return
View
(
user
);
}
//var u = await _UserRepository.Login(user);
var
u
=
new
UserLogin
();
var
url
=
_config
[
"IP"
];
var
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"username"
,
user
.
username
},
{
"pwd"
,
user
.
pwd
},
{
"reqPermFlag[0]"
,
"admin-login"
}
};
var
httpMethod
=
HttpMethod
.
Post
;
int
maxTry
=
2
;
int
currentTry
=
0
;
while
(
currentTry
<
maxTry
)
{
try
{
var
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
// API 呼叫成功,進行相應的處理
u
=
JsonConvert
.
DeserializeObject
<
UserLogin
>(
apiResult
.
Data
.
ToString
());
if
(
u
.
r
==
0
&&
!
string
.
IsNullOrEmpty
(
u
.
token
))
{
string
role
=
""
;
if
(
user
.
username
==
"theone"
)
{
role
=
"Admin"
;
}
else
{
#
region
admin
/
list
url
=
_config
[
"IP"
]
+
"/admin/list"
;
httpMethod
=
HttpMethod
.
Post
;
var
types
=
new
[]
{
"admin"
};
var
types_data
=
new
{
inc
=
types
};
role
=
"Merchant"
;
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
u
.
token
},
{
"types"
,
JsonConvert
.
SerializeObject
(
types_data
)},
};
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
var
adminResponse
=
new
UserResponse
();
if
(
apiResult
.
IsSuccess
)
{
adminResponse
=
JsonConvert
.
DeserializeObject
<
UserResponse
>(
apiResult
.
Data
.
ToString
());
if
(
adminResponse
.
r
==
0
)
{
var
existAdmin
=
adminResponse
.
Users
.
Where
(
u
=>
u
.
username
==
user
.
username
).
FirstOrDefault
();
if
(
existAdmin
!=
null
)
{
if
(
existAdmin
.
enabled
==
1
)
role
=
"Admin"
;
}
}
}
#
endregion
}
#
region
寫入
TOKEN
int
LoginExpireMinute
=
Convert
.
ToInt32
(
_config
[
"LoginExpireMinute"
]);
string
key
=
_config
[
"TokenKey"
];
var
Cookieoptions
=
new
CookieOptions
();
////時間一到就會把Token從Cookie洗掉,如果Expires沒比API的Expires長,則每次Token過期都須重新登入
Cookieoptions
.
Expires
=
DateTime
.
Now
.
AddMinutes
(
LoginExpireMinute
);
//Cookieoptions.SameSite = SameSiteMode.Strict;
Cookieoptions
.
HttpOnly
=
true
;
var
userClaims
=
new
ClaimsIdentity
(
new
[]
{
new
Claim
(
"username"
,
user
.
username
),
new
Claim
(
"token"
,
u
.
token
),
new
Claim
(
ClaimTypes
.
Role
,
role
),
},
CookieAuthenticationDefaults
.
AuthenticationScheme
);
//將 ClaimsIdentity 設定給 ClaimsPrincipal (持有者)
ClaimsPrincipal
principal
=
new
ClaimsPrincipal
(
userClaims
);
//登入動作
try
{
await
HttpContext
.
SignInAsync
(
CookieAuthenticationDefaults
.
AuthenticationScheme
,
principal
,
new
AuthenticationProperties
()
{
//是否可以被刷新
AllowRefresh
=
true
,
// 設置了一個 1 天 有效期的持久化 cookie
IsPersistent
=
true
,
//IsPersistent = false,瀏覽器關閉即刻登出
//用戶頁面停留太久,逾期時間,在此設定的話會覆蓋Startup.cs裡的逾期設定
ExpiresUtc
=
DateTime
.
Now
.
AddMinutes
(
LoginExpireMinute
),
});
}
catch
(
Exception
ex
)
{
logger
.
Trace
(
ex
.
Message
+
ex
.
InnerException
?.
Message
);
}
#
endregion
return
RedirectToAction
(
"Index"
,
"Home"
);
}
else
if
(
u
.
r
==
65796
)
{
currentTry
++;
parameters
[
"reqPermFlag[0]"
]
=
"merchant-login"
;
continue
;
}
else
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
u
.
m
;
return
View
(
apiResult
.
Message
);
}
}
else
{
// API 呼叫失敗,進行相應的錯誤處理
return
BadRequest
(
apiResult
.
Message
);
}
}
catch
(
Exception
ex
)
{
// 處理 API 呼叫發生的例外狀況
return
StatusCode
(
500
,
$"API 呼叫發生錯誤:
{
ex
.
Message
}
"
);
}
}
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"發生錯誤"
;
return
View
();
}
[
Authorize
]
[
HttpGet
]
public
async
Task
<
IActionResult
>
ListUsers
()
{
var
UserResponse
=
new
UserResponse
();
// 取得使用者的 "token" Claim 值
string
token
=
User
.
FindFirstValue
(
"token"
);
...
...
@@ -139,7 +314,6 @@ namespace backstage.Controllers
public
async
Task
<
IActionResult
>
GetUser
(
int
uid
)
{
var
url
=
_config
[
"IP"
]
+
"/user/get"
;
var
httpMethod
=
HttpMethod
.
Post
;
...
...
@@ -175,18 +349,18 @@ namespace backstage.Controllers
{
if
(!
string
.
IsNullOrEmpty
(
GetUserResponse
.
user
.
username
))
{
var
user
=
new
User
();
user
.
name
=
GetUserResponse
.
user
.
name
;
user
.
username
=
GetUserResponse
.
user
.
username
;
//
var user = new User();
//
user.name = GetUserResponse.user.name;
//
user.username = GetUserResponse.user.username;
if
(
GetUserResponse
.
email
!=
null
)
user
.
email
=
GetUserResponse
.
email
;
GetUserResponse
.
user
.
email
=
GetUserResponse
.
email
;
// 使用 JSON 解析工具將 JSON 字串轉換為物件
//var jsonObject = JsonConvert.DeserializeObject<Dictionary<string, string>>(apiResult.Data.ToString());
GetUserResponse
.
user
.
uid
=
uid
;
//user.created_date = DateTime.Parse(jsonObject["created_date"]);
return
View
(
user
);
return
View
(
GetUserResponse
.
user
);
}
}
else
...
...
@@ -213,20 +387,159 @@ namespace backstage.Controllers
return
View
();
}
/// <summary>
/// 修改密碼
/// </summary>
/// <returns></returns>
[
Authorize
]
[
HttpGet
]
public
async
Task
<
IActionResult
>
ChangePassword
(
string
username
,
string
returnUrl
)
{
if
(
User
.
Identity
.
IsAuthenticated
&&
User
.
IsInRole
(
"Admin"
))
{
// 使用者已驗證並具有 "admin" 角色
var
url
=
_config
[
"IP"
]
+
"/user/list"
;
ViewBag
.
returnUrl
=
returnUrl
;
var
httpMethod
=
HttpMethod
.
Post
;
// 取得使用者的 "token" Claim 值
string
token
=
User
.
FindFirstValue
(
"token"
);
var
types
=
new
[]
{
"all"
};
var
types_data
=
new
{
inc
=
types
};
var
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
token
},
{
"types"
,
JsonConvert
.
SerializeObject
(
types_data
)}
};
var
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
try
{
var
UserResponse
=
JsonConvert
.
DeserializeObject
<
UserResponse
>(
apiResult
.
Data
.
ToString
());
if
(
UserResponse
.
r
==
0
)
{
if
(
UserResponse
.
userCount
>
0
)
{
var
existUser
=
UserResponse
.
Users
.
Where
(
u
=>
u
.
username
==
username
).
FirstOrDefault
();
if
(
existUser
==
null
)
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"使用者不存在"
;
return
Redirect
(
"~"
+
returnUrl
);
}
else
{
return
View
(
existUser
);
}
}
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"使用者不存在"
;
return
Redirect
(
"~"
+
returnUrl
);
}
else
if
(
UserResponse
.
r
==
65537
)
{
}
else
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"發生錯誤"
;
return
RedirectToAction
(
returnUrl
);
}
}
catch
(
Exception
e
)
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
e
.
Message
;
return
Redirect
(
"~"
+
returnUrl
);
}
}
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"發生錯誤"
;
return
Redirect
(
"~"
+
returnUrl
);
}
else
{
ViewBag
.
returnUrl
=
returnUrl
;
return
View
();
}
}
[
Authorize
]
[
HttpPost
]
public
async
Task
<
IActionResult
>
ChangePassword
(
User
user
,
string
returnUrl
)
{
var
url
=
_config
[
"IP"
]
+
"/admin/changepassword"
;
if
(
string
.
IsNullOrEmpty
(
user
.
password
))
{
ModelState
.
AddModelError
(
"Password"
,
"密碼不能為空"
);
}
var
httpMethod
=
HttpMethod
.
Post
;
// 取得使用者的 "token" Claim 值
string
token
=
User
.
FindFirstValue
(
"token"
);
var
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
token
},
{
"newpwd"
,
user
.
newPassword
}
};
var
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
var
userAddResponse
=
JsonConvert
.
DeserializeObject
<
UserAddResponse
>(
apiResult
.
Data
.
ToString
());
if
(
userAddResponse
.
r
==
0
)
{
TempData
[
"IsSuccess"
]
=
true
;
TempData
[
"msg"
]
=
"更改密碼成功"
;
return
RedirectToAction
(
"ListUsers"
);
}
else
{
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
JsonConvert
.
SerializeObject
(
userAddResponse
.
m
);
return
View
(
user
);
}
}
return
View
();
}
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpGet
]
public
async
Task
<
IActionResult
>
CreateUser
()
{
return
View
();
}
[
Authorize
]
[
Authorize
(
Policy
=
"AdminOnly"
)
]
[
HttpPost
]
public
async
Task
<
IActionResult
>
CreateUser
(
User
user
)
{
var
url
=
_config
[
"IP"
]
+
"/user/add"
;
if
(
string
.
IsNullOrEmpty
(
user
.
password
))
{
ModelState
.
AddModelError
(
"Password"
,
"密碼不能為空"
);
...
...
@@ -274,7 +587,7 @@ namespace backstage.Controllers
public
async
Task
<
IActionResult
>
GetUser
(
User
user
)
{
// 取得使用者的 "token" Claim 值
string
token
=
User
.
FindFirstValue
(
"token"
);
...
...
@@ -315,8 +628,8 @@ namespace backstage.Controllers
var
existName
=
UserResponse
.
Users
.
Where
(
u
=>
u
.
name
==
user
.
name
).
FirstOrDefault
();
if
(
existName
!=
null
)
{
if
(
existName
.
uid
!=
user
.
uid
)
ModelState
.
AddModelError
(
"name"
,
"name重複"
);
if
(
existName
.
uid
!=
user
.
uid
)
ModelState
.
AddModelError
(
"name"
,
"name重複"
);
}
//檢查username
if
(
string
.
IsNullOrEmpty
(
user
.
username
))
...
...
@@ -337,20 +650,20 @@ namespace backstage.Controllers
existUser
.
name
=
user
.
name
;
existUser
.
username
=
user
.
username
;
//檢查通過
url
=
_config
[
"IP"
]
+
"/user/mod"
;
parameters
=
new
Dictionary
<
string
,
string
>
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
token
},
{
"data"
,
JsonConvert
.
SerializeObject
(
u
ser
)}
{
"data"
,
JsonConvert
.
SerializeObject
(
existU
ser
)}
//{ "types", "{\"inc\":[\"all\"]}"}
};
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
TempData
[
"IsSuccess"
]
=
true
;
...
...
@@ -358,7 +671,7 @@ namespace backstage.Controllers
return
RedirectToAction
(
"ListUsers"
);
}
TempData
[
"IsSuccess"
]
=
false
;
TempData
[
"msg"
]
=
"user_id不存在"
;
return
View
(
existUser
);
...
...
@@ -423,7 +736,7 @@ namespace backstage.Controllers
public
async
Task
<
IActionResult
>
GetDepartment
(
int
id
)
{
var
url
=
_config
[
"IP"
]
+
"/merchant/get"
;
var
httpMethod
=
HttpMethod
.
Post
;
// 取得使用者的 "token" Claim 值
...
...
@@ -461,19 +774,19 @@ namespace backstage.Controllers
return
View
();
}
[
Authorize
]
[
Authorize
(
Policy
=
"AdminOnly"
)
]
[
HttpGet
]
public
async
Task
<
IActionResult
>
CreateDepartment
()
{
return
View
();
}
[
Authorize
]
[
Authorize
(
Policy
=
"AdminOnly"
)
]
[
HttpPost
]
public
async
Task
<
IActionResult
>
CreateDepartment
(
DepartmentForCreate
department
)
{
var
url
=
_config
[
"IP"
]
+
"/merchant/add"
;
if
(
string
.
IsNullOrEmpty
(
department
.
name
))
{
ModelState
.
AddModelError
(
"name"
,
"部門名稱不能為空"
);
...
...
@@ -521,112 +834,6 @@ namespace backstage.Controllers
}
[
HttpPost
]
[
ValidateAntiForgeryToken
]
public
async
Task
<
IActionResult
>
Login
(
User
user
,
string
returnUrl
)
{
if
(!
ModelState
.
IsValid
)
{
return
View
(
user
);
}
//var u = await _UserRepository.Login(user);
var
u
=
new
UserLogin
();
var
url
=
_config
[
"IP"
];
var
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"username"
,
user
.
username
},
{
"pwd"
,
user
.
pwd
},
{
"reqPermFlag[0]"
,
"admin-login"
}
};
var
httpMethod
=
HttpMethod
.
Post
;
try
{
var
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
// API 呼叫成功,進行相應的處理
u
=
JsonConvert
.
DeserializeObject
<
UserLogin
>(
apiResult
.
Data
.
ToString
());
if
(
u
.
r
==
0
&&
!
string
.
IsNullOrEmpty
(
u
.
token
))
{
#
region
寫入
TOKEN
int
LoginExpireMinute
=
Convert
.
ToInt32
(
_config
[
"LoginExpireMinute"
]);
string
key
=
_config
[
"TokenKey"
];
var
Cookieoptions
=
new
CookieOptions
();
////時間一到就會把Token從Cookie洗掉,如果Expires沒比API的Expires長,則每次Token過期都須重新登入
Cookieoptions
.
Expires
=
DateTime
.
Now
.
AddMinutes
(
LoginExpireMinute
);
//Cookieoptions.SameSite = SameSiteMode.Strict;
Cookieoptions
.
HttpOnly
=
true
;
var
userClaims
=
new
ClaimsIdentity
(
new
[]
{
new
Claim
(
"username"
,
user
.
username
),
new
Claim
(
"token"
,
u
.
token
),
},
CookieAuthenticationDefaults
.
AuthenticationScheme
);
//將 ClaimsIdentity 設定給 ClaimsPrincipal (持有者)
ClaimsPrincipal
principal
=
new
ClaimsPrincipal
(
userClaims
);
//登入動作
try
{
await
HttpContext
.
SignInAsync
(
CookieAuthenticationDefaults
.
AuthenticationScheme
,
principal
,
new
AuthenticationProperties
()
{
//是否可以被刷新
AllowRefresh
=
true
,
// 設置了一個 1 天 有效期的持久化 cookie
IsPersistent
=
true
,
//IsPersistent = false,瀏覽器關閉即刻登出
//用戶頁面停留太久,逾期時間,在此設定的話會覆蓋Startup.cs裡的逾期設定
ExpiresUtc
=
DateTime
.
Now
.
AddMinutes
(
LoginExpireMinute
),
});
}
catch
(
Exception
ex
)
{
logger
.
Trace
(
ex
.
Message
+
ex
.
InnerException
?.
Message
);
}
#
endregion
return
RedirectToAction
(
"Index"
,
"Home"
);
}
else
{
// API 呼叫失敗,進行相應的錯誤處理
return
BadRequest
(
apiResult
.
Message
);
}
}
else
{
// API 呼叫失敗,進行相應的錯誤處理
return
BadRequest
(
apiResult
.
Message
);
}
}
catch
(
Exception
ex
)
{
// 處理 API 呼叫發生的例外狀況
return
StatusCode
(
500
,
$"API 呼叫發生錯誤:
{
ex
.
Message
}
"
);
}
}
/// <summary>
/// enable做兩件事情,user加入admin,並且enable=true,
...
...
@@ -635,7 +842,7 @@ namespace backstage.Controllers
/// <param name="uid"></param>
/// <param name="isAdmin"></param>
/// <returns></returns>
[
Authorize
]
[
Authorize
(
Policy
=
"AdminOnly"
)
]
[
HttpPost
]
public
async
Task
<
ResultModel
>
AdminAddAjax
(
int
uid
,
bool
isAdmin
)
{
...
...
@@ -783,7 +990,99 @@ namespace backstage.Controllers
[
Authorize
(
Policy
=
"AdminOnly"
)]
[
HttpPost
]
public
async
Task
<
ResultModel
>
UserEnableAjax
(
int
uid
,
int
enabled
)
{
var
result
=
new
ResultModel
();
// 取得使用者的 "token" Claim 值
string
token
=
User
.
FindFirstValue
(
"token"
);
#
region
user
/
list
var
url
=
_config
[
"IP"
]
+
"/user/list"
;
var
httpMethod
=
HttpMethod
.
Post
;
var
types
=
new
[]
{
"all"
};
var
types_data
=
new
{
inc
=
types
};
var
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
token
},
{
"types"
,
JsonConvert
.
SerializeObject
(
types_data
)},
{
"email"
,
"1"
},
{
"phone"
,
"1"
}
//{ "types", "{\"inc\":[\"all\"]}"}
};
var
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
var
UserResponse
=
JsonConvert
.
DeserializeObject
<
UserResponse
>(
apiResult
.
Data
.
ToString
());
if
(
UserResponse
.
userCount
>
0
)
{
var
existUser
=
UserResponse
.
Users
.
Where
(
u
=>
u
.
uid
==
uid
).
FirstOrDefault
();
if
(
existUser
==
null
)
{
result
.
IsSuccess
=
false
;
result
.
Message
=
"user_id不存在"
;
return
result
;
}
//檢查通過
url
=
_config
[
"IP"
]
+
"/user/mod"
;
var
data
=
new
{
uid
=
uid
,
enabled
=
enabled
};
parameters
=
new
Dictionary
<
string
,
string
>
{
{
"token"
,
token
},
{
"data"
,
JsonConvert
.
SerializeObject
(
data
)
}
};
apiResult
=
await
_callApi
.
CallAPI
(
url
,
parameters
,
httpMethod
);
if
(
apiResult
.
IsSuccess
)
{
var
response
=
JsonConvert
.
DeserializeObject
<
Response
>(
apiResult
.
Data
.
ToString
());
if
(
response
.
r
==
0
)
{
result
.
IsSuccess
=
true
;
result
.
Message
=
"權限調整成功"
;
return
result
;
}
}
result
.
IsSuccess
=
false
;
result
.
Message
=
"發生錯誤"
;
return
result
;
}
result
.
IsSuccess
=
false
;
result
.
Message
=
"發生錯誤"
;
return
result
;
}
result
.
IsSuccess
=
false
;
result
.
Message
=
"發生錯誤"
;
return
result
;
#
endregion
}
[
HttpGet
]
public
async
Task
<
IActionResult
>
Logout
()
{
...
...
@@ -794,6 +1093,5 @@ namespace backstage.Controllers
}
}
}
\ No newline at end of file
Merchant Token Vault Management/backstage/Models/Users/User.cs
View file @
e1cd39b5
...
...
@@ -18,6 +18,7 @@ namespace backstage.Models.Users
public
string
pwd
{
get
;
set
;
}
//新增使用者用
public
string
password
{
get
;
set
;
}
public
string
newPassword
{
get
;
set
;
}
public
List
<
emaildata
>
email
{
get
;
set
;
}
public
int
locked
{
get
;
set
;
}
...
...
Merchant Token Vault Management/backstage/Startup.cs
View file @
e1cd39b5
...
...
@@ -39,7 +39,8 @@ namespace backstage
services
.
AddControllersWithViews
();
services
.
AddAuthorization
();
services
.
AddAuthentication
(
CookieAuthenticationDefaults
.
AuthenticationScheme
).
AddCookie
(
"Cookies"
,
option
=>
services
.
AddAuthentication
(
CookieAuthenticationDefaults
.
AuthenticationScheme
)
.
AddCookie
(
"Cookies"
,
option
=>
{
option
.
Cookie
.
HttpOnly
=
true
;
...
...
@@ -47,11 +48,26 @@ namespace backstage
option
.
LogoutPath
=
new
PathString
(
"/User/Logout"
);
option
.
Cookie
.
Name
=
"backstage"
;
option
.
Cookie
.
SameSite
=
SameSiteMode
.
Strict
;
option
.
Events
=
new
CookieAuthenticationEvents
{
OnRedirectToAccessDenied
=
context
=>
{
context
.
Response
.
Redirect
(
"/Home/AccessDenied"
);
// 將使用者重新導向到 Home/AccessDenied
return
Task
.
CompletedTask
;
}
};
////�n�J���Įɶ�
});
services
.
AddAuthorization
(
options
=>
{
options
.
AddPolicy
(
"AdminOnly"
,
policy
=>
{
// 設定需要 "Admin" 角色的策略
policy
.
RequireRole
(
"Admin"
);
});
});
// �N Session �s�b ASP.NET Core �O���餤
services
.
AddDistributedMemoryCache
();
services
.
AddHttpContextAccessor
();
...
...
Merchant Token Vault Management/backstage/Views/Home/Index.cshtml
View file @
e1cd39b5
...
...
@@ -11,67 +11,47 @@
}
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="page-header">
<h3 class="page-title">數據統計</h3>
</div>
@*
<div class="row">
<div class="col-lg-
6 grid-margin stretch
-card">
<div class="row">
<div class="col-lg-
4 col-md-6 grid-margin stretch-card dashboard
-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">代辦事項</h4>
<div class="add-items d-flex">
<input id="new_task" type="text" class="form-control todo-list-input" placeholder="要做什麼呢?">
<button class="add btn btn-primary font-weight-bold todo-list-add-btn white-nowrap" id="add-task">新增</button>
<h4 class="card-title">Token Vault Entry 總數量</h4>
<div class="card-content text-center">
<img src="images/admin-vault.svg" class="img-fuild">
<p class="number text-center">200</p>
</div>
<div class="list-wrapper scrollbar"
>
<ul class="d-flex flex-column-reverse todo-list todo-list-custom"
>
</div
>
</div
>
</div>
</ul>
<div class="col-lg-4 col-md-6 grid-margin stretch-card dashboard-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">本月新增 Token Vualt Entry 數量</h4>
<div class="card-content text-center">
<img src="/images/admin-vault-add.svg" class="img-fuild">
<p class="number text-center">10</p>
</div>
</div>
</div>
</div>
<div class="col-lg-6 grid-margin stretch-card">
<div class="col-lg-4 col-md-6 grid-margin stretch-card dashboard-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">購買項目到期提醒(前後一個月)</h4>
<div class="table-scroll scrollbar">
<table class="table table-hover">
<thead>
<tr>
<th>到期日</th>
<th>項目</th>
<th>聯絡人</th>
<th>聯絡手機</th>
<th>登記姓名</th>
</tr>
</thead>
<tbody>
@if (ViewBag.ToBeExpired != null)
{
@foreach (var i in ViewBag.ToBeExpired)
{
<tr>
<td><label class="text-danger">@i.DueDate</label></td>
<td>@i.ItemName</td>
<td>@i.CustomerName</td>
<td>@i.CustomerPhone</td>
<td>@i.Name</td>
</tr>
}
}
</tbody>
</table>
<h4 class="card-title">本月修改 Token Vualt Entry 數量</h4>
<div class="card-content text-center">
<img src="/images/admin-vault-edit.svg" class="img-fuild">
<p class="number text-center">7</p>
</div>
</div>
</div>
</div>
</div>*@
</div>
...
...
@@ -79,43 +59,12 @@
<script src="~/js/Home.js"></script>
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
var msg = '@TempData["msg"]';
var IsSuccess = '@TempData["IsSuccess"]';
console.log(IsSuccess + msg);
if (msg != '') {
showAlert(IsSuccess, msg);
}
@*$(function () {
let eventsArr = [];
let eventsTable = document.getElementById("eventsTable");
let trElems = eventsTable.getElementsByTagName("tr")
for (let tr of trElems) {
let tdElems = tr.getElementsByTagName("td");
let eventObj = {
id: tdElems[0].innerText,
title: tdElems[1].innerText,
start: tdElems[2].innerText,
};
eventsArr.push(eventObj);
}
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'zh-cn',
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prevYear prev,next nextYear today',
center: 'title',
right: 'dayGridMonth timeGridWeek timeGridDay'
},
buttonText: {
today: '今天',
month: '月',
week: '周',
day: '日',
},
events: eventsArr
});
calendar.render();
})*@
</script>
}
\ No newline at end of file
Merchant Token Vault Management/backstage/Views/Shared/_Layout.cshtml
View file @
e1cd39b5
...
...
@@ -75,15 +75,15 @@
</div>
</a>
<div
class=
"dropdown-menu navbar-dropdown"
aria-labelledby=
"profileDropdown"
>
<a
class=
"dropdown-item"
asp-controller=
"User"
asp-action=
"ChangePassword"
>
<a
class=
"dropdown-item"
asp-controller=
"User"
asp-action=
"ChangePassword"
asp-route-username=
"@Context.User.Claims.FirstOrDefault(m => m.Type == "
username
").
Value
"
asp-route-returnUrl=
"@Context.Request.Path"
>
<i
class=
"mdi mdi-lock-open mr-2"
></i>
更改密碼
</a>
<a
class=
"dropdown-item"
asp-controller=
"User"
asp-action=
"Register"
>
@*
<a
class=
"dropdown-item"
asp-controller=
"User"
asp-action=
"Register"
>
<i
class=
"mdi mdi-account-plus mr-2"
></i>
註冊管理員
</a>
<a
class=
"dropdown-item"
asp-controller=
"UserManage"
asp-action=
"GetUserManage"
>
</a>
*@
@*
<a
class=
"dropdown-item"
asp-controller=
"UserManage"
asp-action=
"GetUserManage"
>
<i
class=
"mdi mdi-account-details mr-2"
></i>
帳號管理
</a>
</a>
*@
<div
class=
"dropdown-divider"
></div>
<a
class=
"dropdown-item"
asp-controller=
"User"
asp-action=
"Logout"
>
<i
class=
"mdi mdi-logout mr-2 text-danger"
></i>
登出
...
...
Merchant Token Vault Management/backstage/Views/TokenVault/List.cshtml
View file @
e1cd39b5
...
...
@@ -2,7 +2,10 @@
@{
ViewData["Title"] = "TokenVault列表管理";
}
@{
bool isAdmin = User.IsInRole("admin");
string disabledClass = isAdmin ? "" : "disabled";
}
<div class="page-header">
<h3 class="page-title">TokenVault列表管理</h3>
...
...
@@ -11,7 +14,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
...
...
@@ -23,7 +26,7 @@
<div class="col-md-12">
<ul class="breadcrumb breadcrumb_memberGo">
<li class="breadcrumb-item active">資料代碼保險庫</li>
</ul>
</div>
</div>
...
...
@@ -38,7 +41,7 @@
</select>
</div>
<div class="col-md-auto">
<a type="button" class="btn btn-info float-right mb-2" asp-action="CreateTokenVault">Create</a>
<a type="button" class="btn btn-info float-right mb-2
@disabledClass
" asp-action="CreateTokenVault">Create</a>
</div>
</div>
<div class="row">
...
...
@@ -149,7 +152,7 @@
$('#selectDepartmentList').change(function () {
var selectedValue = $(this).val(); // 獲取選擇的值
loadData(selectedValue);
});
// 定義 AJAX 請求函式,將選單值傳遞至後端並填入 tbody
...
...
Merchant Token Vault Management/backstage/Views/TokenVault/ListFields.cshtml
View file @
e1cd39b5
...
...
@@ -2,7 +2,10 @@
@{
ViewData["Title"] = "Fields列表管理";
}
@{
bool isAdmin = User.IsInRole("admin");
string disabledClass = isAdmin ? "" : "disabled";
}
@section header{
<script>
//欄位檢查
...
...
@@ -39,7 +42,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
...
...
@@ -75,7 +78,7 @@
</div>
</div>
<div style="float: right;">
<a type="button" class="btn btn-info float-right mb-2
"
data-toggle="modal" data-target="#myModal">Create</a>
<a type="button" class="btn btn-info float-right mb-2
@disabledClass"
data-toggle="modal" data-target="#myModal">Create</a>
</div>
</div>
<div>
...
...
@@ -129,8 +132,8 @@
</div>
</div>
<!-- MODAL -->
<!-- MODAL -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
...
...
Merchant Token Vault Management/backstage/Views/TokenVault/ListMasks.cshtml
View file @
e1cd39b5
...
...
@@ -2,7 +2,10 @@
@{
ViewData["Title"] = "Mask列表管理";
}
@{
bool isAdmin = User.IsInRole("admin");
string disabledClass = isAdmin ? "" : "disabled";
}
<div class="page-header">
<h3 class="page-title">Mask列表管理</h3>
...
...
@@ -11,7 +14,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
...
...
@@ -57,7 +60,7 @@
</table>
<div class="newBlock">
@*<button type="button" class="btn btn-mainblue-hollow" onclick="window.location.href='tokenVault_fields.html'"><img src="images/memberGo/apiKey/back_o_icons8-undo-90.png">返回</button>*@
<button type="button" class="btn btn-mainblue-solid" data-toggle="modal" data-target="#new-field-mask"><img src="~/images/memberGo/add.png">新增遮罩</button>
<button type="button" class="btn btn-mainblue-solid
@disabledClass
" data-toggle="modal" data-target="#new-field-mask"><img src="~/images/memberGo/add.png">新增遮罩</button>
</div>
<div class="table-responsive">
...
...
@@ -73,6 +76,7 @@
<th style=" border-left: solid 1px #d9d9d9;">ID</th>
<th>名稱</th>
<th>種類</th>
<th>遮罩</th>
<th>唯一值</th>
<th>設定</th>
<th>修改</th>
...
...
@@ -88,6 +92,7 @@
<td class="item">@m.id</td>
<td class="mask_name">@m.name</td>
<td class="content">@m.type</td>
<td class="content">@m.mask</td>
<td class="item">@(m.is_unique==1?"是":"否")</td>
<td class="content">@m.setting</td>
<td>
...
...
@@ -140,7 +145,7 @@
<form id="createMaskForm" class="form-horizontal0" method="post" autocomplete="off">
<div id="errorMsg" asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<input hidden name="mask_id"
>
<input hidden name="mask_id">
<input hidden name="merchant_id" value="@ViewBag.merchant_id">
<input hidden name="field_id" value="@ViewBag.field_id">
<input hidden name="vault_id" value="@ViewBag.vault_id">
...
...
@@ -173,7 +178,7 @@
<label class="control-labe" for="userName">種類:</label>
<div class="form-group">
<div class="dropdown bootstrap-select selecter form-control -tokenization">
<select title="請選遮罩種類(單選)" id="maskType" class="selectpicker selecter form-control selectpicker-tokenization" onchange="showMaskSettingsAdv()">
<select title="請選遮罩種類(單選)"
name="type"
id="maskType" class="selectpicker selecter form-control selectpicker-tokenization" onchange="showMaskSettingsAdv()">
<option class="bs-title-option" value=""></option>
<option value="0">0</option>
<option value="1">1</option>
...
...
@@ -191,7 +196,7 @@
<label class="control-labe" for="userName">mask:</label>
<div class="form-group">
<div class="dropdown bootstrap-select selecter form-control -tokenization">
<select id="mask" title="請選擇mask(單選)" class="selectpicker selecter form-control selectpicker-tokenization">
<select id="mask" title="請選擇mask(單選)"
name="mask"
class="selectpicker selecter form-control selectpicker-tokenization">
<option class="bs-title-option" value=""></option>
<option>0</option>
<option>1</option>
...
...
@@ -222,7 +227,7 @@
</div>
</div>
<div class="SubmitBlock">
<button id="createMaskBtn" type="button" class="btn btn-mainblue-solid btnSubmit">
新增
</button>
<button id="createMaskBtn" type="button" class="btn btn-mainblue-solid btnSubmit">
送出
</button>
<button type="button" class="btn btn-mainblue-hollow btnReset" data-dismiss="modal">取消</button>
</div>
</form>
...
...
@@ -323,12 +328,30 @@
//編輯mask
$(".editMaskBtn").click(function (event) {
var selectMaskId = 0;
selectMaskId = $(this).closest("tr").find("td:first").text();
console.log('selectMaskId=' + selectMaskId);
$('input[name="mask_id"]').val(selectMaskId);
$('#new-field-mask .modal-title').text('編輯遮罩');
$('new-field-mask').modal();
var name = $("#memberGoTbl_masksList tr").filter(function () {
return $(this).find("td:first-child").text().trim() === selectMaskId;
}).find("td:nth-child(2)").text();
$("#new-field-mask input[name='name']").val(name);
var is_unique = $("#memberGoTbl_masksList tr").filter(function () {
return $(this).find("td:first-child").text().trim() === selectMaskId;
}).find("td:nth-child(5)").text();
$("#new-field-mask input[name='is_unique']").prop("checked", is_unique);
var type = $("#memberGoTbl_masksList tr").filter(function () {
return $(this).find("td:first-child").text().trim() === selectMaskId;
}).find("td:nth-child(3)").text();
$("#new-field-mask select[name='type'] option").filter(function () {
return $(this).val() === type;
}).prop("selected", true);
$('#new-field-mask').modal();
//$.ajax({
// url: '/TokenVault/EditMask',
// type: 'POST',
...
...
Merchant Token Vault Management/backstage/Views/TokenVault/ListUsers.cshtml
View file @
e1cd39b5
...
...
@@ -2,7 +2,10 @@
@{
ViewData["Title"] = "欄位Users列表管理";
}
@{
bool isAdmin = User.IsInRole("admin");
string disabledClass = isAdmin ? "" : "disabled";
}
<div class="page-header">
<h3 class="page-title">欄位Users列表管理</h3>
...
...
@@ -11,7 +14,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
...
...
@@ -31,7 +34,7 @@
<div>
<a type="button" class="btn btn-info float-right mb-2" data-toggle="modal" data-target="#myModal">Add User</a>
<a type="button" class="btn btn-info float-right mb-2
@disabledClass
" data-toggle="modal" data-target="#myModal">Add User</a>
<div class="rank-table">
<div class="table-responsive">
<table class="table table-striped expense-color">
...
...
@@ -54,33 +57,35 @@
{
@foreach (var i in Model)
{
<tr id="@i.id" class="expense-color">
<td>@i.id</td>
<td>@i.name</td>
<td>@i.username</td>
<td>@i.masksText</td>
<td>
@if (i.allow_decrypt == 1)
{<span>✔</span>}
</td>
<td>
@if (i.allow_new == 1)
{<span>✔</span>}
</td>
<td>
@if (i.allow_update == 1)
{<span>✔</span>}
</td>
<td>@if (i.allow_del == 1)
{<span>✔</span>}</td>
<td>@i.default_mask_id</td>
<td>
<a href="tokenVault_fields_users.html" class="btn btnPermission btn-sm">移除使用者</a>
</td>
</tr>
}
<tr id="@i.id" class="expense-color">
<td>@i.id</td>
<td>@i.name</td>
<td>@i.username</td>
<td>@i.masksText</td>
<td>
@if (i.allow_decrypt == 1)
{<span>✔</span>}
</td>
<td>
@if (i.allow_new == 1)
{<span>✔</span>}
</td>
<td>
@if (i.allow_update == 1)
{<span>✔</span>}
</td>
<td>
@if (i.allow_del == 1)
{<span>✔</span>}
</td>
<td>@i.default_mask_id</td>
<td>
<a href="tokenVault_fields_users.html" class="btn btnPermission btn-sm">移除使用者</a>
</td>
</tr>
}
}
</tbody>
...
...
@@ -110,12 +115,12 @@
</div>
<div class="modal-body">
<select id="selectUser" class="form-control" asp-items="ViewBag.users">
<!-- 其他用户选项 -->
</select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary"
id="confirmBtn"
data-dismiss="modal">確認</button>
<button type="button" class="btn btn-primary"
id="confirmBtn"
data-dismiss="modal">確認</button>
</div>
</div>
</div>
...
...
Merchant Token Vault Management/backstage/Views/User/ChangePassword.cshtml
0 → 100644
View file @
e1cd39b5
@model backstage.Models.Users.User
@{
ViewData["Title"] = "更改密碼";
}
@{
bool isAdmin = User.IsInRole("Admin");
string displayStyle = isAdmin ? "" : "display:none;";
}
<!-- partial -->
<div class="page-header">
<h3 class="page-title">更改密碼</h3>
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
<div class="col-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">更改密碼</h4>
<form class="forms-sample" method="post" asp-action="ChangePassword" asp-route-returnUrl="@ViewBag.returnUrl" autocomplete="off">
<div id="errorMsg" asp-validation-summary="All" class="text-danger"></div>
<input hidden asp-for="username" />
<p class="form-title card-description">帳號資訊</p>
<div class="row" style="@displayStyle">
<div class="col-md-4 form-group required">
<label asp-for="uid" class="col-form-label" for=""></label>
<input asp-for="uid" type="text" class="form-control" disabled>
</div>
<div class="col-md-4 form-group required">
<label asp-for="name" class="col-form-label" for=""></label>
<input asp-for="name" type="text" class="form-control" disabled>
</div>
<div class="col-md-4 form-group required">
<label asp-for="username" class="col-form-label" for=""></label>
<input asp-for="username" type="text" class="form-control" disabled>
</div>
</div>
<p class="form-title card-description">修改密碼</p>
<div class="row">
<div class="col-md-4 form-group required">
<label asp-for="password" class="col-form-label" for="">目前密碼</label>
<input asp-for="password" type="password" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-4 form-group required">
<label asp-for="newPassword" class="col-form-label">新密碼</label>
<input asp-for="newPassword" type="password" class="form-control" id="newPWD">
</div>
</div>
<div class="row">
<div class="col-md-4 form-group required">
<label class="col-form-label">確認新密碼</label>
<input class="form-control" type="password" id="confirmPWD">
<span id="passwordMatchError" class="text-danger" style="display: none;">兩次輸入的密碼不一致</span>
</div>
</div>
<button type="submit" class="btn btn-primary mr-2">送出</button>
<a type="button" class="btn btn-light" asp-action="Index" , asp-controller="Home">取消</a>
</form>
</div>
</div>
</div>
</div>
@section Scripts{
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
$(document).ready(function () {
var msg = '@TempData["msg"]';
var IsSuccess = '@TempData["IsSuccess"]';
console.log(IsSuccess + msg);
if (msg != '') {
showAlert(IsSuccess, msg);
}
$(".forms-sample").submit(function (event) {
event.preventDefault();
$('input').removeAttr('disabled');
this.submit();
});
$('#confirmPWD').keyup(function () {
var newPassword = $('#newPWD').val();
var confirmPassword = $(this).val();
if (newPassword !== confirmPassword) {
$('#passwordMatchError').show();
} else {
$('#passwordMatchError').hide();
}
});
})
</script>
}
Merchant Token Vault Management/backstage/Views/User/GetUser.cshtml
View file @
e1cd39b5
...
...
@@ -13,7 +13,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
<div class="col-12 grid-margin stretch-card">
...
...
@@ -44,44 +44,67 @@
</div>
<div class="col-md-4 form-group ">
<label asp-for="username" class="col-form-label" for="username"></label>
<input asp-for="username" class="form-control" id="username">
<input asp-for="username" class="form-control" id="username"
disabled
>
<span asp-validation-for="username" class="text-danger"></span>
</div>
</div>
<div class="row">
@if (Model.email!=null)
@if (Model.email.Count > 0)
@if (Model.email != null)
{
for (int i = 0; i < Model.email.Count; i++)
{
@foreach (var item in Model.email)
{
<div class="col-md-2 form-group">
<label asp-for="@
item.type" class="col-form-label" for="item.type">type
</label>
<input
value="@item
.type" class="form-control" />
<span asp-validation-for="@
item
.type" class="text-danger"></span>
<label asp-for="@
Model.email[i].type" class="col-form-label" for="emailType">類型
</label>
<input
name="email[@i].type" value="@Model.email[i]
.type" class="form-control" />
<span asp-validation-for="@
Model.email[i]
.type" class="text-danger"></span>
</div>
<div class="col-md-6 form-group">
<label asp-for="@
item.email" class="col-form-label" for="item.email">email
</label>
<input
value="@item
.email" class="form-control" />
<span asp-validation-for="@
item
.email" class="text-danger"></span>
<label asp-for="@
Model.email[i].email" class="col-form-label" for="emailAddress">電子郵件
</label>
<input
name="email[@i].email" value="@Model.email[i]
.email" class="form-control" />
<span asp-validation-for="@
Model.email[i]
.email" class="text-danger"></span>
</div>
}
}
}
</div>
@*<div class="row">
<div class="col-md-4 form-group ">
<label asp-for="password" class="col-form-label" for=""></label>
<input asp-for="password" type="text" class="form-control" id="">
<span asp-validation-for="password" class="text-danger"></span>
<!--<div class="row" id="">
<div class="col-md-2 form-group">
<label class="col-form-label" >新增類型</label>-->
@*<input name="email[@(Model.email != null ? Model.email.Count : 0)].type" class="form-control" />*@
<!--<input class="form-control" />
</div>
<div class="col-md-6 form-group">
<label class="col-form-label">新增電子郵件</label>-->
@*<input name="email[@(Model.email != null ? Model.email.Count : 0)].email" class="form-control" />*@
<!--<input class="form-control"/>
</div>
</div>-->
<p class="form-title card-description">修改密碼</p>
<div class="row">
</div>*@
<div class="col-md-4 form-group required">
<label asp-for="password" class="col-form-label" for="">目前密碼</label>
<input asp-for="password" type="password" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-4 form-group required">
<label asp-for="newPassword" class="col-form-label">新密碼</label>
<input asp-for="newPassword" type="password" class="form-control" id="newPWD">
</div>
</div>
<div class="row">
<div class="col-md-4 form-group required">
<label class="col-form-label">確認新密碼</label>
<input class="form-control" type="password" id="confirmPWD">
<span id="passwordMatchError" class="text-danger" style="display: none;">兩次輸入的密碼不一致</span>
</div>
</div>
...
...
@@ -105,15 +128,24 @@
if (msg != '') {
showAlert(IsSuccess, msg);
}
$(".forms-sample").submit(function (event) {
event.preventDefault();
$('input').removeAttr('disabled');
this.submit();
});
})
</script>
...
...
Merchant Token Vault Management/backstage/Views/User/ListDepartments.cshtml
View file @
e1cd39b5
@model backstage.Models.Users.DepartmentsResponse
@{
bool isAdmin = User.IsInRole("Admin");
string disabledClass = isAdmin ? "" : "disabled";
}
<div class="page-header">
<h3 class="page-title">Department List</h3>
...
...
@@ -7,13 +11,13 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
<div class="col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<a type="button" class="btn btn-info float-right mb-2" asp-action="CreateDepartment">Create</a>
<a type="button" class="btn btn-info float-right mb-2
@disabledClass
" asp-action="CreateDepartment">Create</a>
@*列表*@
<div class="">
...
...
@@ -23,8 +27,8 @@
<th>merchant_id</th>
<th>name</th>
@*<th>address</th>
<th>country_id</th>
<th>postcode</th>*@
<th>country_id</th>
<th>postcode</th>*@
<th>phone</th>
@*<th>fax</th>*@
@*<th>vatid</th>*@
...
...
@@ -36,8 +40,8 @@
<th>user_natid_verify</th>
<th>enabled_transaction</th>*@
@*<th>merchant_type</th>
<th>merchant_level</th>
<th>tts</th>*@
<th>merchant_level</th>
<th>tts</th>*@
</tr>
...
...
@@ -53,21 +57,21 @@
<td>@i.merchant_id</td>
<td>@i.name</td>
@*<td>@i.address</td>
<td>@i.country_id</td>
<td>@i.postcode</td>*@
<td>@i.country_id</td>
<td>@i.postcode</td>*@
<td>@i.phone</td>
@*<td>@i.fax</td>*@
@*<td>@i.vatid</td>
<td>@i.enabled</td>*@
<td>@i.enabled</td>*@
<td>@i.creation_date</td>
@*<td>@i.vatid_verify</td>
<td>@i.deposit_book_verify</td>
<td>@i.user_natid_verify</td>
<td>@i.enabled_transaction</td>*@
@*<td>@i.merchant_type</td>
<td>@i.merchant_level</td>
<td>@i.tts</td>*@
<td>@i.merchant_level</td>
<td>@i.tts</td>*@
@*<td class="text-right">
<a class="btn btn-primary" asp-action="EditEventItem" asp-route-id="@i.Id"><i class="mdi mdi-grease-pencil"></i>編輯</a>
...
...
@@ -92,7 +96,7 @@
@section Scripts{
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
var msg = '@TempData["msg"]';
var IsSuccess = '@TempData["IsSuccess"]';
console.log(IsSuccess + msg);
...
...
Merchant Token Vault Management/backstage/Views/User/ListUsers.cshtml
View file @
e1cd39b5
@model backstage.Models.Users.UserResponse
@{
bool isAdmin = User.IsInRole("admin");
string disabledClass = isAdmin ? "" : "disabled";
}
<div class="page-header">
<h3 class="page-title">User List</h3>
<input id="msg" hidden value="@TempData["msg"]" />
...
...
@@ -7,7 +10,7 @@
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div class="floating-msg" id="msgDiv"></div>
<div class="floating-msg" id="msgDiv"></div>
</div>
<div class="row">
...
...
@@ -15,7 +18,7 @@
<div class="card">
<div class="card-body">
<div id="adminStatus" style="float: left;">User count:@ViewBag.userCount / Admin count:@ViewBag.adminCount </div>
<a type="button" class="btn btn-info float-right mb-2" asp-action="CreateUser">Create</a>
<a type="button" class="btn btn-info float-right mb-2
@disabledClass
" asp-action="CreateUser">Create</a>
@*列表*@
<div class="">
...
...
@@ -32,11 +35,11 @@
<th>enabled</th>
<th>Admin</th>
@*<th>birthdate</th>
<th>marital_status</th>
<th>gender</th>
<th>education</th>
<th>natid</th>
<th>lang</th>*@
<th>marital_status</th>
<th>gender</th>
<th>education</th>
<th>natid</th>
<th>lang</th>*@
</tr>
...
...
@@ -48,41 +51,41 @@
@foreach (var i in Model.Users)
{
<tr
data-user-id="@i.uid">
<td class="userRow">@i.uid</td>
<td class="userRow">@i.name</td>
@*<td>@i.name_en</td>*@
<td class="userRow">@i.username</td>
@if (i.email != null)
@if (i.email.Count > 0)
{
<td>@i.email[0].email</td>
}
else
{
<td></td>
}
@*<td>@i.locked</td>*@
<td>@i.creation_date</td>
<td> <input type="checkbox" class="toggleButton" @(i.enabled==1 ? "checked" : "") disabled
></td>
<td> <input type="checkbox" data-uid="@i.uid" class="toggleButton isAdmin" @(i.isAdmin ? "checked" : "")></td>
@*@if (i.isAdmin)
{ <td>是</td>}
else { <td></td>}*@
@*<td>@i.birthdate</td>
<td>@i.marital_status</td>
<td>@i.gender</td>
<td>@i.education</td>
<td>@i.natid</td>
<td>@i.lang</td>*@
@*<td class="text-right">
<a class="btn btn-primary" asp-action="EditEventItem" asp-route-id="@i.Id"><i class="mdi mdi-grease-pencil"></i>編輯</a>
<button class="btn btn-inverse-danger" id="eventItem-delete-btn" data-id="@i.Id" data-name="@i.Title"><i class="mdi mdi-delete-forever"></i>刪除</button>
</td>*@
</tr>
<tr
data-user-id="@i.uid">
<td class="userRow">@i.uid</td>
<td class="userRow">@i.name</td>
@*<td>@i.name_en</td>*@
<td class="userRow">@i.username</td>
@if (i.email != null)
@if (i.email.Count > 0)
{
<td>@i.email[0].email</td>
}
else
{
<td></td>
}
@*<td>@i.locked</td>*@
<td>@i.creation_date</td>
<td> <input type="checkbox" data-uid="@i.uid" class="toggleButton isEnable" @(i.enabled == 1 ? "checked" : "")
></td>
<td> <input type="checkbox" data-uid="@i.uid" class="toggleButton isAdmin" @(i.isAdmin ? "checked" : "")></td>
@*@if (i.isAdmin)
{ <td>是</td>}
else { <td></td>}*@
@*<td>@i.birthdate</td>
<td>@i.marital_status</td>
<td>@i.gender</td>
<td>@i.education</td>
<td>@i.natid</td>
<td>@i.lang</td>*@
@*<td class="text-right">
<a class="btn btn-primary" asp-action="EditEventItem" asp-route-id="@i.Id"><i class="mdi mdi-grease-pencil"></i>編輯</a>
<button class="btn btn-inverse-danger" id="eventItem-delete-btn" data-id="@i.Id" data-name="@i.Title"><i class="mdi mdi-delete-forever"></i>刪除</button>
</td>*@
</tr>
}
}
...
...
@@ -100,12 +103,12 @@
@section Scripts{
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
var msg = '@TempData["msg"]';
var msg = '@TempData["msg"]';
var IsSuccess = '@TempData["IsSuccess"]';
console.log(IsSuccess + msg);
if (msg != '') {
showAlert(IsSuccess, msg);
}
}
$('.userRow').each(function () {
var uid = $(this).find('td:first-child').text(); // 獲取行中的 UID 值
...
...
@@ -124,7 +127,7 @@
size: 'small',
onSwitchChange: function (event, state) {
var uid = $(this).data('uid');
var isAdmin = $(this).is(':checked');
var isAdmin = $(this).is(':checked')
?1:0
;
// 使用 AJAX 發送請求,處理狀態變更事件
$.ajax({
...
...
@@ -134,6 +137,35 @@
success: function (response) {
// 在成功回調中處理回應
console.log(response);
showAlert(response.isSuccess, response.message)
},
error: function (error) {
// 在錯誤回調中處理錯誤
console.log(error);
}
});
}
});
$('.isEnable').bootstrapSwitch({
onText: 'ON',
offText: 'OFF',
onColor: 'success',
offColor: 'danger',
size: 'small',
onSwitchChange: function (event, state) {
var uid = $(this).data('uid');
var enabled = $(this).is(':checked') ? 1 : 0;;
// 使用 AJAX 發送請求,處理狀態變更事件
$.ajax({
url: '/User/UserEnableAjax',
type: 'POST',
data: { uid: uid, enabled: enabled },
success: function (response) {
// 在成功回調中處理回應
console.log(response);
showAlert(response.isSuccess,response.message)
},
error: function (error) {
// 在錯誤回調中處理錯誤
...
...
Merchant Token Vault Management/backstage/Views/User/Login.cshtml
View file @
e1cd39b5
...
...
@@ -110,7 +110,16 @@
<script
src=
"~/lib/jquery-ui/jquery-ui.min.js"
></script>
<!--END jquery ui datepicker-->
<script
src=
"~/js/jquery.ba-dotimeout.js"
></script>
<script
src=
"~/lib/jquery.ba-dotimeout.js"
></script>
</body>
</html>
<script>
var
msg
=
'@TempData["msg"]'
;
var
IsSuccess
=
'@TempData["IsSuccess"]'
;
console
.
log
(
IsSuccess
+
msg
);
if
(
msg
!=
''
)
{
showAlert
(
IsSuccess
,
msg
);
}
</script>
\ No newline at end of file
Merchant Token Vault Management/backstage/wwwroot/css/style.css
View file @
e1cd39b5
...
...
@@ -19283,4 +19283,17 @@ tbody {
background-color
:
transparent
;
padding
:
10px
;
border
:
0
;
}
.dashboard-card
.card-title
{
margin-bottom
:
40px
;
}
.dashboard-card
.card-content
img
{
max-width
:
160px
;
}
.dashboard-card
.card-content
.number
{
font-size
:
5rem
;
color
:
#35A9E1
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment