Explorar el Código

Add public-admin orders site with search/pagination, CI/CD pipeline support

- New AdminOrdersController + view: table of Orders with search by
  email/jurisdiction #, pagination (20/page), and per-row mailto link
  to resend the order-continue URL
- OrdersRepository: add GetAll() and SearchPaged() (LIKE search,
  PagedQuery-based pagination)
- MailtoEncode helper added to core/helpers.asp (mailto-safe URL
  encoding: %20 not +)
- Controller registered in autoload + ControllerRegistry
- public-admin/ folder: dedicated Default.asp routes, web.config with
  192.168.1.0/24 ipSecurity, production template with same restriction
- applicationhost.config: second IIS Express site (Admin Web Site,
  port 8081)
- run_site.cmd: launches both sites (public in separate window,
  admin in foreground)
- build-release.ps1: public-admin in allow-list, swaps its
  web.config from production template
- deploy-iis-remote-apply.ps1: optional admin site/app-pool config
  + restart
- deploy-iis.ps1: -AdminSiteName/-AdminAppPool/-AdminBaseUrl params,
  admin smoke test
master
Daniel Covington hace 9 horas
padre
commit
5cc19f7c56
Se han modificado 83 ficheros con 1696 adiciones y 3 borrados
  1. +65
    -0
      app/controllers/AdminOrdersController.asp
  2. +2
    -1
      app/controllers/autoload_controllers.asp
  3. +74
    -0
      app/models/OrdersRepository.asp
  4. +87
    -0
      app/views/AdminOrders/index.asp
  5. +8
    -0
      applicationhost.config
  6. +8
    -0
      core/helpers.asp
  7. +1
    -0
      core/lib.ControllerRegistry.asp
  8. +13
    -0
      public-admin/Default.asp
  9. +1100
    -0
      public-admin/css/styles.css
  10. BIN
      public-admin/images/KCI ELECTION printing (white).png
  11. BIN
      public-admin/images/KCI ELECTION printing.png
  12. BIN
      public-admin/images/KCI geo.png
  13. BIN
      public-admin/images/KCI_design print mail.png
  14. BIN
      public-admin/images/back.png
  15. BIN
      public-admin/images/blurple.png
  16. BIN
      public-admin/images/certified-election-mail-service-provider.png
  17. BIN
      public-admin/images/purple-envelope-colors/Aqua.png
  18. BIN
      public-admin/images/purple-envelope-colors/Black.png
  19. BIN
      public-admin/images/purple-envelope-colors/Blue.png
  20. BIN
      public-admin/images/purple-envelope-colors/Brown.png
  21. BIN
      public-admin/images/purple-envelope-colors/BurlyWood.png
  22. BIN
      public-admin/images/purple-envelope-colors/Chocolate.png
  23. BIN
      public-admin/images/purple-envelope-colors/Clay.png
  24. BIN
      public-admin/images/purple-envelope-colors/Coral.png
  25. BIN
      public-admin/images/purple-envelope-colors/CornflowerBlue.png
  26. BIN
      public-admin/images/purple-envelope-colors/Crimson.png
  27. BIN
      public-admin/images/purple-envelope-colors/DarkOrange.png
  28. BIN
      public-admin/images/purple-envelope-colors/DeepPink.png
  29. BIN
      public-admin/images/purple-envelope-colors/DeepSkyBlue.png
  30. BIN
      public-admin/images/purple-envelope-colors/DimGray.png
  31. BIN
      public-admin/images/purple-envelope-colors/DodgerBlue.png
  32. BIN
      public-admin/images/purple-envelope-colors/FireBrick.png
  33. BIN
      public-admin/images/purple-envelope-colors/ForestGreen.png
  34. BIN
      public-admin/images/purple-envelope-colors/Fuchsia.png
  35. BIN
      public-admin/images/purple-envelope-colors/Gold.png
  36. BIN
      public-admin/images/purple-envelope-colors/Goldenrod.png
  37. BIN
      public-admin/images/purple-envelope-colors/Green.png
  38. BIN
      public-admin/images/purple-envelope-colors/HotPink.png
  39. BIN
      public-admin/images/purple-envelope-colors/Indigo.png
  40. BIN
      public-admin/images/purple-envelope-colors/LightSeaGreen.png
  41. BIN
      public-admin/images/purple-envelope-colors/Lime.png
  42. BIN
      public-admin/images/purple-envelope-colors/LimeGreen.png
  43. BIN
      public-admin/images/purple-envelope-colors/LtGreen.png
  44. BIN
      public-admin/images/purple-envelope-colors/MediumOrchid.png
  45. BIN
      public-admin/images/purple-envelope-colors/MediumPurple.png
  46. BIN
      public-admin/images/purple-envelope-colors/MediumTurquoise.png
  47. BIN
      public-admin/images/purple-envelope-colors/MintGreen.png
  48. BIN
      public-admin/images/purple-envelope-colors/Navy.png
  49. BIN
      public-admin/images/purple-envelope-colors/Olive.png
  50. BIN
      public-admin/images/purple-envelope-colors/OliveDrab.png
  51. BIN
      public-admin/images/purple-envelope-colors/Orange.png
  52. BIN
      public-admin/images/purple-envelope-colors/OrangeRed.png
  53. BIN
      public-admin/images/purple-envelope-colors/Orchid.png
  54. BIN
      public-admin/images/purple-envelope-colors/PastelBlue.png
  55. BIN
      public-admin/images/purple-envelope-colors/PastelPink.png
  56. BIN
      public-admin/images/purple-envelope-colors/PastelPurple.png
  57. BIN
      public-admin/images/purple-envelope-colors/PastelYellow.png
  58. BIN
      public-admin/images/purple-envelope-colors/Peru.png
  59. BIN
      public-admin/images/purple-envelope-colors/Pink.png
  60. BIN
      public-admin/images/purple-envelope-colors/Purple.png
  61. BIN
      public-admin/images/purple-envelope-colors/Red.png
  62. BIN
      public-admin/images/purple-envelope-colors/RoyalBlue.png
  63. BIN
      public-admin/images/purple-envelope-colors/SaddleBrown.png
  64. BIN
      public-admin/images/purple-envelope-colors/SeaGreen.png
  65. BIN
      public-admin/images/purple-envelope-colors/Sienna.png
  66. BIN
      public-admin/images/purple-envelope-colors/Silver.png
  67. BIN
      public-admin/images/purple-envelope-colors/SkyBlue.png
  68. BIN
      public-admin/images/purple-envelope-colors/SteelBlue.png
  69. BIN
      public-admin/images/purple-envelope-colors/Tan.png
  70. BIN
      public-admin/images/purple-envelope-colors/Teal.png
  71. BIN
      public-admin/images/purple-envelope-colors/Tomato.png
  72. BIN
      public-admin/images/purple-envelope-colors/Turquoise.png
  73. BIN
      public-admin/images/purple-envelope-colors/Violet.png
  74. BIN
      public-admin/images/purple-envelope-colors/White.png
  75. BIN
      public-admin/images/purple-envelope-colors/Yellow.png
  76. BIN
      public-admin/images/swaggy backer.png
  77. BIN
      public-admin/images/swaggy geo.png
  78. +129
    -0
      public-admin/web.config
  79. +119
    -0
      public-admin/web.config.production.template
  80. +8
    -1
      run_site.cmd
  81. +11
    -1
      scripts/build-release.ps1
  82. +30
    -0
      scripts/deploy-iis-remote-apply.ps1
  83. +41
    -0
      scripts/deploy-iis.ps1

+ 65
- 0
app/controllers/AdminOrdersController.asp Ver fichero

@@ -0,0 +1,65 @@
<%
Class AdminOrdersController_Class
Private m_useLayout
Private m_title

Private Sub Class_Initialize()
m_useLayout = True
m_title = "Orders"
End Sub

Public Property Get useLayout
useLayout = m_useLayout
End Property

Public Property Let useLayout(v)
m_useLayout = v
End Property

Public Property Get Title
Title = m_title
End Property

Public Property Let Title(v)
m_title = v
End Property

'-------------------------------------------------------------------------------------------------------------------
' GET: list orders (searchable by email/jurisdiction #, paginated) with a mailto link to
' resend the continuation URL for each.
'-------------------------------------------------------------------------------------------------------------------
Public Sub Index()
Dim orders, searchTerm, pageNum, perPage, pageCount, recordCount
perPage = 20

searchTerm = Trim(Request.QueryString("q"))

If IsNumeric(Request.QueryString("page")) And CLng(Request.QueryString("page")) >= 1 Then
pageNum = CLng(Request.QueryString("page"))
Else
pageNum = 1
End If

Set orders = OrdersRepository().SearchPaged(searchTerm, perPage, pageNum, pageCount, recordCount)

' If the requested page is past the last one (e.g. a stale bookmark after a search
' narrows the results), clamp to the last real page and re-fetch.
If pageCount > 0 And pageNum > pageCount Then
pageNum = pageCount
Set orders = OrdersRepository().SearchPaged(searchTerm, perPage, pageNum, pageCount, recordCount)
End If
%>
<!--#include file="../views/AdminOrders/index.asp" -->
<%
End Sub

End Class

Dim AdminOrdersController_Class__Singleton
Function AdminOrdersController()
If IsEmpty(AdminOrdersController_Class__Singleton) Then
Set AdminOrdersController_Class__Singleton = New AdminOrdersController_Class
End If
Set AdminOrdersController = AdminOrdersController_Class__Singleton
End Function
%>

+ 2
- 1
app/controllers/autoload_controllers.asp Ver fichero

@@ -10,4 +10,5 @@
<!--#include file="ErrorController.asp" -->
<!--#include file="RequestOrderController.asp" -->
<!--#include file="OrderController.asp" -->
<!--#include file="OrderApiController.asp" -->
<!--#include file="OrderApiController.asp" -->
<!--#include file="AdminOrdersController.asp" -->

+ 74
- 0
app/models/OrdersRepository.asp Ver fichero

@@ -18,6 +18,80 @@ Class OrdersRepository_Class
CreateOrder = token
End Function

' Returns a Scripting.Dictionary of Scripting.Dictionary rows for every order, newest first.
Public Function GetAll()
Dim rs, results, order
Set results = Server.CreateObject("Scripting.Dictionary")

Set rs = DAL.Query( _
"SELECT OrderID, Email, JurisdictionNumber, Token, TokenExpiresAt, TokenUsedAt, CreatedAt FROM Orders ORDER BY OrderID DESC", _
Empty)

Do While Not rs.EOF
Set order = Server.CreateObject("Scripting.Dictionary")
order.Add "OrderID", rs("OrderID").Value
order.Add "Email", rs("Email").Value
order.Add "JurisdictionNumber", rs("JurisdictionNumber").Value
order.Add "Token", rs("Token").Value
order.Add "TokenExpiresAt", rs("TokenExpiresAt").Value
order.Add "TokenUsedAt", rs("TokenUsedAt").Value
order.Add "CreatedAt", rs("CreatedAt").Value
results.Add rs("OrderID").Value, order
rs.MoveNext
Loop

Destroy rs
Set GetAll = results
End Function

' Returns a Scripting.Dictionary of Scripting.Dictionary rows (newest first) matching searchTerm
' against Email or JurisdictionNumber (all rows if searchTerm is blank), one page at a time.
' page_count/record_count are returned by reference for building pagination controls.
Public Function SearchPaged(searchTerm, per_page, page_num, ByRef page_count, ByRef record_count)
Dim sql, params
sql = "SELECT OrderID, Email, JurisdictionNumber, Token, TokenExpiresAt, TokenUsedAt, CreatedAt FROM Orders"
page_count = 0
record_count = 0

If Len(Trim(searchTerm)) > 0 Then
sql = sql & " WHERE Email LIKE ? OR JurisdictionNumber LIKE ?"
params = Array("%" & searchTerm & "%", "%" & searchTerm & "%")
Else
params = Empty
End If

sql = sql & " ORDER BY OrderID DESC"

Dim rs : Set rs = DAL.PagedQuery(sql, params, per_page, page_num)

If Not rs.EOF Then
rs.PageSize = per_page
rs.AbsolutePage = page_num
page_count = rs.PageCount
record_count = rs.RecordCount
End If

Dim results, order, x
Set results = Server.CreateObject("Scripting.Dictionary")
x = 0
Do While (per_page <= 0 Or x < per_page) And Not rs.EOF
Set order = Server.CreateObject("Scripting.Dictionary")
order.Add "OrderID", rs("OrderID").Value
order.Add "Email", rs("Email").Value
order.Add "JurisdictionNumber", rs("JurisdictionNumber").Value
order.Add "Token", rs("Token").Value
order.Add "TokenExpiresAt", rs("TokenExpiresAt").Value
order.Add "TokenUsedAt", rs("TokenUsedAt").Value
order.Add "CreatedAt", rs("CreatedAt").Value
results.Add rs("OrderID").Value, order
x = x + 1
rs.MoveNext
Loop

Destroy rs
Set SearchPaged = results
End Function

' Returns a Scripting.Dictionary describing the order matching the given token, or Nothing if not found.
Public Function FindByToken(token)
Dim rs


+ 87
- 0
app/views/AdminOrders/index.asp Ver fichero

@@ -0,0 +1,87 @@
<section style="padding: 32px 0;">
<h1>Orders</h1>

<form method="get" action="" class="row g-2 align-items-center" style="margin-bottom: 16px;">
<div class="col-auto">
<input type="text" name="q" value="<%= H(searchTerm) %>" class="form-control" placeholder="Search by email or jurisdiction #" />
</div>
<div class="col-auto">
<button type="submit" class="button button-secondary">Search</button>
</div>
<% If Len(searchTerm) > 0 Then %>
<div class="col-auto">
<a href="?">Clear</a>
</div>
<% End If %>
</form>

<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Order ID</th>
<th>Email</th>
<th>Jurisdiction #</th>
<th>Created</th>
<th>Token Status</th>
<th>Resend Link</th>
</tr>
</thead>
<tbody>
<% If orders.Count = 0 Then %>
<tr><td colspan="6"><% If Len(searchTerm) > 0 Then %>No orders match your search.<% Else %>No orders found.<% End If %></td></tr>
<% Else
Dim orderKey, order, tokenStatus, continueUrl, mailtoBody, mailtoHref
For Each orderKey In orders.Keys
Set order = orders(orderKey)

If Not IsNull(order("TokenUsedAt")) Then
tokenStatus = "Used"
ElseIf order("TokenExpiresAt") < Now() Then
tokenStatus = "Expired"
Else
tokenStatus = "Active"
End If

continueUrl = "https://pe.kentcommunications.com/order/continue?token=" & MailtoEncode(order("Token"))
mailtoBody = "Continue your order here: " & continueUrl
mailtoHref = "mailto:" & order("Email") & _
"?subject=" & MailtoEncode("Continue your Purple Envelope order") & _
"&body=" & MailtoEncode(mailtoBody)
%>
<tr>
<td><%= H(order("OrderID")) %></td>
<td><%= H(order("Email")) %></td>
<td><%= H(order("JurisdictionNumber")) %></td>
<td><%= H(order("CreatedAt")) %></td>
<td><%= H(tokenStatus) %></td>
<td><a class="button button-secondary" href="<%= H(mailtoHref) %>">Email link</a></td>
</tr>
<%
Next
End If
%>
</tbody>
</table>

<% If pageCount > 1 Then
Dim qsBase, pn
qsBase = "?q=" & Server.URLEncode(searchTerm) & "&page="
%>
<nav aria-label="Orders pagination">
<ul class="pagination">
<li class="page-item<% If pageNum <= 1 Then %> disabled<% End If %>">
<a class="page-link" href="<%= H(qsBase & (pageNum - 1)) %>">Previous</a>
</li>
<% For pn = 1 To pageCount %>
<li class="page-item<% If pn = pageNum Then %> active<% End If %>">
<a class="page-link" href="<%= H(qsBase & pn) %>"><%= pn %></a>
</li>
<% Next %>
<li class="page-item<% If pageNum >= pageCount Then %> disabled<% End If %>">
<a class="page-link" href="<%= H(qsBase & (pageNum + 1)) %>">Next</a>
</li>
</ul>
</nav>
<p><%= recordCount %> order<% If recordCount <> 1 Then %>s<% End If %> found.</p>
<% End If %>
</section>

+ 8
- 0
applicationhost.config Ver fichero

@@ -162,6 +162,14 @@
<binding protocol="http" bindingInformation=":8080:localhost" />
</bindings>
</site>
<site name="Admin Web Site" id="2" serverAutoStart="true">
<application path="/">
<virtualDirectory path="/" physicalPath="%ASPC_STARTER_ROOT%public-admin" />
</application>
<bindings>
<binding protocol="http" bindingInformation=":8081:localhost" />
</bindings>
</site>
<siteDefaults>
<!-- To enable logging, please change the below attribute "enabled" to "true" -->
<logFile logFormat="W3C" directory="%AppData%\Microsoft\IISExpressLogs" enabled="false" />


+ 8
- 0
core/helpers.asp Ver fichero

@@ -201,6 +201,14 @@ Function H(s)
End Function


'===============================================================================================================================
' mailto: links require %20 for spaces, not "+" - Server.URLEncode produces "+", so swap it back after encoding.
'===============================================================================================================================
Function MailtoEncode(s)
MailtoEncode = Replace(Server.URLEncode(s), "+", "%20")
End Function


'=======================================================================================================================
' Adapted from Tolerable library
'=======================================================================================================================


+ 1
- 0
core/lib.ControllerRegistry.asp Ver fichero

@@ -18,6 +18,7 @@ Class ControllerRegistry_Class
RegisterController "requestordercontroller"
RegisterController "ordercontroller"
RegisterController "orderapicontroller"
RegisterController "adminorderscontroller"
End Sub

Private Sub Class_Terminate()


+ 13
- 0
public-admin/Default.asp Ver fichero

@@ -0,0 +1,13 @@
<!--#include file="..\core\autoload_core.asp" -->

<%
' Admin site routes
router.AddRoute "GET", "/", "AdminOrdersController", "Index"
router.AddRoute "GET", "", "AdminOrdersController", "Index"
router.AddRoute "GET", "/orders", "AdminOrdersController", "Index"
router.AddRoute "GET", "/404", "ErrorController", "NotFound"

' Dispatch the request (resolves route and executes controller action)
MVC.DispatchRequest Request.ServerVariables("REQUEST_METHOD"), _
TrimQueryParams(Request.ServerVariables("HTTP_X_ORIGINAL_URL"))
%>

+ 1100
- 0
public-admin/css/styles.css
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


BIN
public-admin/images/KCI ELECTION printing (white).png Ver fichero

Antes Después
Anchura: 716  |  Altura: 868  |  Tamaño: 57KB

BIN
public-admin/images/KCI ELECTION printing.png Ver fichero

Antes Después
Anchura: 730  |  Altura: 912  |  Tamaño: 57KB

BIN
public-admin/images/KCI geo.png Ver fichero

Antes Después
Anchura: 2072  |  Altura: 266  |  Tamaño: 93KB

BIN
public-admin/images/KCI_design print mail.png Ver fichero

Antes Después
Anchura: 343  |  Altura: 138  |  Tamaño: 17KB

BIN
public-admin/images/back.png Ver fichero

Antes Después
Anchura: 656  |  Altura: 413  |  Tamaño: 110KB

BIN
public-admin/images/blurple.png Ver fichero

Antes Después
Anchura: 567  |  Altura: 162  |  Tamaño: 3.6KB

BIN
public-admin/images/certified-election-mail-service-provider.png Ver fichero

Antes Después
Anchura: 1800  |  Altura: 1800  |  Tamaño: 520KB

BIN
public-admin/images/purple-envelope-colors/Aqua.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 772B

BIN
public-admin/images/purple-envelope-colors/Black.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 522B

BIN
public-admin/images/purple-envelope-colors/Blue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 773B

BIN
public-admin/images/purple-envelope-colors/Brown.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/BurlyWood.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Chocolate.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Clay.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 852B

BIN
public-admin/images/purple-envelope-colors/Coral.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/CornflowerBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Crimson.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 852B

BIN
public-admin/images/purple-envelope-colors/DarkOrange.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 773B

BIN
public-admin/images/purple-envelope-colors/DeepPink.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/DeepSkyBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 774B

BIN
public-admin/images/purple-envelope-colors/DimGray.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 847B

BIN
public-admin/images/purple-envelope-colors/DodgerBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/FireBrick.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/ForestGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/Fuchsia.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 844B

BIN
public-admin/images/purple-envelope-colors/Gold.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Goldenrod.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Green.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 773B

BIN
public-admin/images/purple-envelope-colors/HotPink.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/Indigo.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/LightSeaGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Lime.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 773B

BIN
public-admin/images/purple-envelope-colors/LimeGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/LtGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/MediumOrchid.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/MediumPurple.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/MediumTurquoise.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/MintGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Navy.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 775B

BIN
public-admin/images/purple-envelope-colors/Olive.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 772B

BIN
public-admin/images/purple-envelope-colors/OliveDrab.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Orange.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 774B

BIN
public-admin/images/purple-envelope-colors/OrangeRed.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 774B

BIN
public-admin/images/purple-envelope-colors/Orchid.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/PastelBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/PastelPink.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 852B

BIN
public-admin/images/purple-envelope-colors/PastelPurple.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/PastelYellow.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/Peru.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Pink.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Purple.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 844B

BIN
public-admin/images/purple-envelope-colors/Red.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 773B

BIN
public-admin/images/purple-envelope-colors/RoyalBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/SaddleBrown.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/SeaGreen.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Sienna.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Silver.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 847B

BIN
public-admin/images/purple-envelope-colors/SkyBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/SteelBlue.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Tan.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 852B

BIN
public-admin/images/purple-envelope-colors/Teal.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 772B

BIN
public-admin/images/purple-envelope-colors/Tomato.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 851B

BIN
public-admin/images/purple-envelope-colors/Turquoise.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 852B

BIN
public-admin/images/purple-envelope-colors/Violet.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 850B

BIN
public-admin/images/purple-envelope-colors/White.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 846B

BIN
public-admin/images/purple-envelope-colors/Yellow.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 150  |  Tamaño: 772B

BIN
public-admin/images/swaggy backer.png Ver fichero

Antes Después
Anchura: 1026  |  Altura: 630  |  Tamaño: 108KB

BIN
public-admin/images/swaggy geo.png Ver fichero

Antes Después
Anchura: 900  |  Altura: 900  |  Tamaño: 57KB

+ 129
- 0
public-admin/web.config Ver fichero

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<appSettings>
<!--
Access connection string.
IMPORTANT: Change Data Source to the real physical path
to your webdata.accdb file.
-->
<add key="ConnectionString"
value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Development\ASP CLASSIC\Purple Envelope Orders Site\db\webdata.accdb;Persist Security Info=False;" />

<!-- Environment flag (Development / Staging / Production) -->
<add key="Environment" value="Development" />

<!-- Flash message display duration in milliseconds -->
<add key="FlashMessageTimeout" value="8000" />

<!-- 404 error page redirect countdown in seconds -->
<add key="Error404RedirectSeconds" value="5" />

<!-- Cache expiration year for static content -->
<add key="CacheExpirationYear" value="2030" />

<!-- Maximum characters to display in table cells before truncating -->
<add key="TableCellMaxLength" value="90" />

<!-- Character threshold for textarea vs input field in forms -->
<add key="FormTextareaThreshold" value="100" />

<!-- Enable error logging to file (true/false) -->
<add key="EnableErrorLogging" value="false" />

<!-- Error log file path (if EnableErrorLogging is true) -->
<add key="ErrorLogPath" value="C:\YourApp\logs\errors.log" />

<!-- Enable cache-busting for URLs and assets (true/false) -->
<add key="EnableCacheBusting" value="false" />

<!-- Cache-bust parameter name (default: "v") -->
<add key="CacheBustParamName" value="v" />

<!--
SMTP settings used by CDOEmail for outbound order emails.
PLACEHOLDER VALUES - replace with real SMTP server details before going live.
-->
<add key="SmtpServer" value="kentcommunications-com.mail.protection.outlook.com" />
<add key="SmtpPort" value="25" />
<add key="SmtpUsername" value="" />
<add key="SmtpPassword" value="" />
<add key="SmtpUseSSL" value="false" />
<add key="SmtpFromAddress" value="no-reply@kentcommunications.com" />

<!-- Hours before an order continuation link (token) expires -->
<add key="OrderTokenExpirationHours" value="24" />

<!--
Jurisdiction number validation (request-order form). The list is essentially static
reference data, so it's cached in Application scope rather than fetched on every
submission - see JurisdictionCacheMinutes.
-->
<add key="JurisdictionApiUrl" value="http://192.168.1.40:8081/api/jurisdictions" />
<add key="JurisdictionCacheMinutes" value="60" />

<!--
Cloudflare Turnstile (CAPTCHA) keys. These are DEV keys - replace with production
site/secret keys before going live.
-->
<add key="TurnstileSiteKey" value="0x4AAAAAAEUPEPHEnA9hPgbw" />
<add key="TurnstileSecretKey" value="0x4AAAAAAEUPEFnbhCe6ttr_Mq6yCozxRkg" />
</appSettings>

<system.webServer>
<!-- Default document for the site root -->
<defaultDocument>
<files>
<clear />
<add value="Default.asp" />
</files>
</defaultDocument>

<!-- URL Rewrite: send everything through Default.asp except static assets -->
<rewrite>
<rules>
<rule name="Rewrite to Default.asp" stopProcessing="true">
<match url="^(?!Default\.asp$|css/|js/|images/|aspunit/|favicon\.ico$).*$" />

<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>

<action type="Rewrite" url="/Default.asp" />
</rule>
</rules>
</rewrite>

<!-- Strip the Server response header (reveals IIS version) - IIS 10+ only -->
<!-- Restrict this admin site to the internal 192.168.1.0/24 network only.
Requires the IIS "IP and Domain Restrictions" role feature to be installed. -->
<security>
<requestFiltering removeServerHeader="true" />
<ipSecurity allowUnlisted="false" denyAction="Forbidden">
<add ipAddress="192.168.1.0" subnetMask="255.255.255.0" allowed="true" />
</ipSecurity>
</security>

<!-- Strip framework-identifying headers that IIS/ASP.NET modules may add -->
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
<!-- URL Rewrite module adds this in IIS Express, leaking the physical file path -->
<remove name="X-SourceFiles" />
</customHeaders>
</httpProtocol>
</system.webServer>


<location path="css">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="01:00:00" />
</staticContent>
</system.webServer>
</location>
</configuration>


+ 119
- 0
public-admin/web.config.production.template Ver fichero

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<appSettings>
<!-- Access connection string. Points at the persistent data folder, outside the
deploy directory so a redeploy (which wipes and re-extracts the deploy dir) never
touches it. -->
<add key="ConnectionString"
value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\inetpub\data\webdata.accdb;Persist Security Info=False;" />

<!-- Environment flag (Development / Staging / Production) -->
<add key="Environment" value="Production" />

<!-- Flash message display duration in milliseconds -->
<add key="FlashMessageTimeout" value="8000" />

<!-- 404 error page redirect countdown in seconds -->
<add key="Error404RedirectSeconds" value="5" />

<!-- Cache expiration year for static content -->
<add key="CacheExpirationYear" value="2030" />

<!-- Maximum characters to display in table cells before truncating -->
<add key="TableCellMaxLength" value="90" />

<!-- Character threshold for textarea vs input field in forms -->
<add key="FormTextareaThreshold" value="100" />

<!-- Enable error logging to file (true/false) -->
<add key="EnableErrorLogging" value="true" />

<!-- Error log file path - also outside the deploy directory so logs survive a redeploy. -->
<add key="ErrorLogPath" value="C:\inetpub\data\logs\errors.log" />

<!-- Enable cache-busting for URLs and assets (true/false) -->
<add key="EnableCacheBusting" value="false" />

<!-- Cache-bust parameter name (default: "v") -->
<add key="CacheBustParamName" value="v" />

<!-- SMTP settings used by CDOEmail for outbound order emails. -->
<add key="SmtpServer" value="kentcommunications-com.mail.protection.outlook.com" />
<add key="SmtpPort" value="25" />
<add key="SmtpUsername" value="" />
<add key="SmtpPassword" value="" />
<add key="SmtpUseSSL" value="false" />
<add key="SmtpFromAddress" value="no-reply@kentcommunications.com" />

<!-- Hours before an order continuation link (token) expires -->
<add key="OrderTokenExpirationHours" value="24" />

<!--
Jurisdiction number validation (request-order form). The list is essentially static
reference data, so it's cached in Application scope rather than fetched on every
submission - see JurisdictionCacheMinutes.
-->
<add key="JurisdictionApiUrl" value="http://192.168.1.40:8081/api/jurisdictions" />
<add key="JurisdictionCacheMinutes" value="60" />

<!-- Cloudflare Turnstile (CAPTCHA) keys. -->
<add key="TurnstileSiteKey" value="0x4AAAAAAEUPEPHEnA9hPgbw" />
<add key="TurnstileSecretKey" value="0x4AAAAAAEUPEFnbhCe6ttr_Mq6yCozxRkg" />
</appSettings>

<system.webServer>
<!-- Default document for the site root -->
<defaultDocument>
<files>
<clear />
<add value="Default.asp" />
</files>
</defaultDocument>

<!-- URL Rewrite: send everything through Default.asp except static assets -->
<rewrite>
<rules>
<rule name="Rewrite to Default.asp" stopProcessing="true">
<match url="^(?!Default\.asp$|css/|js/|images/|aspunit/|favicon\.ico$).*$" />

<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>

<action type="Rewrite" url="/Default.asp" />
</rule>
</rules>
</rewrite>

<!-- Strip the Server response header (reveals IIS version) - IIS 10+ only -->
<!-- Restrict this admin site to the internal 192.168.1.0/24 network only.
Requires the IIS "IP and Domain Restrictions" role feature to be installed. -->
<security>
<requestFiltering removeServerHeader="true" />
<ipSecurity allowUnlisted="false" denyAction="Forbidden">
<add ipAddress="192.168.1.0" subnetMask="255.255.255.0" allowed="true" />
</ipSecurity>
</security>

<!-- Strip framework-identifying headers that IIS/ASP.NET modules may add -->
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
<!-- URL Rewrite module adds this in IIS Express, leaking the physical file path -->
<remove name="X-SourceFiles" />
</customHeaders>
</httpProtocol>
</system.webServer>

<location path="css">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="01:00:00" />
</staticContent>
</system.webServer>
</location>
</configuration>

+ 8
- 1
run_site.cmd Ver fichero

@@ -1,4 +1,11 @@
@echo off
setlocal
set "ASPC_STARTER_ROOT=%~dp0"
"C:\Program Files (x86)\IIS Express\iisexpress.exe" /config:"%~dp0applicationhost.config"
set "IISEXPRESS=C:\Program Files (x86)\IIS Express\iisexpress.exe"
set "CONFIG=%~dp0applicationhost.config"

rem IIS Express only starts one site per process when /site is specified, so the
rem public-facing site is launched in its own window and the admin site runs in
rem this one. Close both windows to stop both sites.
start "Public Site (port 8080)" "%IISEXPRESS%" /config:"%CONFIG%" /site:"Development Web Site"
"%IISEXPRESS%" /config:"%CONFIG%" /site:"Admin Web Site"

+ 11
- 1
scripts/build-release.ps1 Ver fichero

@@ -30,7 +30,7 @@ $ErrorActionPreference = 'Stop'
# the migration runner (+ its generator siblings, harmless to ship alongside it). Only
# db\migrations is kept under db - never db\webdata.accdb, even if something ever put a
# stray copy there.
$KeepTopLevel = @('app', 'core', 'public', 'scripts', 'db')
$KeepTopLevel = @('app', 'core', 'public', 'public-admin', 'scripts', 'db')
$KeepUnderDb = @('migrations')

$repoRoot = Split-Path $PSScriptRoot -Parent
@@ -82,6 +82,16 @@ try {
Copy-Item $templatePath $liveConfig -Force
Remove-Item (Join-Path $OutDir 'public\web.config.production.template') -ErrorAction SilentlyContinue

$adminTemplatePath = Join-Path $repoRoot 'public-admin\web.config.production.template'
if(Test-Path (Join-Path $OutDir 'public-admin')){
if(Test-Path $adminTemplatePath){
$adminLiveConfig = Join-Path $OutDir 'public-admin\web.config'
Copy-Item $adminTemplatePath $adminLiveConfig -Force
Remove-Item (Join-Path $OutDir 'public-admin\web.config.production.template') -ErrorAction SilentlyContinue
Write-Host " public-admin\web.config swapped in from web.config.production.template"
}
}

Write-Host "Release built at $OutDir"
Write-Host " public\web.config swapped in from web.config.production.template"
} finally {


+ 30
- 0
scripts/deploy-iis-remote-apply.ps1 Ver fichero

@@ -17,6 +17,8 @@ param(
[Parameter(Mandatory = $true)][string]$SiteName,
[Parameter(Mandatory = $true)][string]$AppPool,
[Parameter(Mandatory = $true)][string]$DbPath,
[string]$AdminSiteName = '',
[string]$AdminAppPool = '',
[switch]$RunMigrations = $true
)

@@ -69,6 +71,23 @@ Set-ItemProperty ('IIS:\Sites\' + $SiteName) -Name applicationPool -Value $AppPo
# dev machine, which needs the 32-bit one - so the app pool stays 64-bit here.
Set-ItemProperty ('IIS:\AppPools\' + $AppPool) -Name enable32BitAppOnWin64 -Value $false

# --- Admin site ---
$adminPublicDir = Join-Path $RemoteDir 'public-admin'
if(![string]::IsNullOrWhiteSpace($AdminSiteName) -and (Test-Path $adminPublicDir)){
if(!(Get-Website -Name $AdminSiteName -ErrorAction SilentlyContinue)){
throw "IIS admin site '$AdminSiteName' does not exist yet. Create the site and app pool once manually before running this deploy."
}
Write-Host "Configuring admin site $AdminSiteName"
Stop-Website -Name $AdminSiteName -ErrorAction SilentlyContinue
if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
Stop-WebAppPool -Name $AdminAppPool -ErrorAction SilentlyContinue
Set-ItemProperty ('IIS:\Sites\' + $AdminSiteName) -Name applicationPool -Value $AdminAppPool
Set-ItemProperty ('IIS:\AppPools\' + $AdminAppPool) -Name enable32BitAppOnWin64 -Value $false
icacls $dataDir /grant ("IIS AppPool\" + $AdminAppPool + ":(OI)(CI)(M)") /T | Out-Null
}
Set-ItemProperty ('IIS:\Sites\' + $AdminSiteName) -Name physicalPath -Value $adminPublicDir
}

if($RunMigrations){
Write-Host 'Running pending migrations'
Push-Location $RemoteDir
@@ -88,4 +107,15 @@ if((Get-WebAppPoolState -Name $AppPool).Value -eq 'Started'){
}
Start-Website $SiteName

if(![string]::IsNullOrWhiteSpace($AdminSiteName)){
if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
if((Get-WebAppPoolState -Name $AdminAppPool).Value -eq 'Started'){
Restart-WebAppPool -Name $AdminAppPool
} else {
Start-WebAppPool -Name $AdminAppPool
}
}
Start-Website $AdminSiteName
}

Write-Host 'Remote apply complete.'

+ 41
- 0
scripts/deploy-iis.ps1 Ver fichero

@@ -26,8 +26,11 @@ param(
[string]$RemoteDir = 'C:\inetpub\wwwroot\Purple_Envelop_Order_Site',
[string]$SiteName = 'PurpleEnvelopes',
[string]$AppPool = 'PurpleEnvelopes',
[string]$AdminSiteName = '',
[string]$AdminAppPool = '',
[string]$DbPath = 'C:\inetpub\data\webdata.accdb',
[string]$BaseUrl = 'https://pe.kentcommunications.com/',
[string]$AdminBaseUrl = '',
[switch]$RunMigrations = $true,
[string]$SshExe = 'ssh',
[string]$ScpExe = 'scp'
@@ -101,6 +104,12 @@ $remoteCommandParts = @(
'-AppPool', ('"' + $AppPool + '"'),
'-DbPath', ('"' + $DbPath + '"')
)
if(![string]::IsNullOrWhiteSpace($AdminSiteName)){
$remoteCommandParts += @('-AdminSiteName', ('"' + $AdminSiteName + '"'))
}
if(![string]::IsNullOrWhiteSpace($AdminAppPool)){
$remoteCommandParts += @('-AdminAppPool', ('"' + $AdminAppPool + '"'))
}
if($RunMigrations){ $remoteCommandParts += '-RunMigrations' }

Write-Host "Applying release on $RemoteTarget"
@@ -147,4 +156,36 @@ if($failed){
throw 'Smoke test failed - see above'
}

# --- 6. Admin site smoke test ---
if(![string]::IsNullOrWhiteSpace($AdminBaseUrl)){
Write-Host 'Smoke testing admin site...'
$adminChecks = @(
@{ Path = '/'; Expect = 200 }
)
foreach($check in $adminChecks){
$url = $AdminBaseUrl.TrimEnd('/') + $check.Path
try {
$response = Invoke-WebRequest -UseBasicParsing -Uri $url -TimeoutSec 30
$status = [int]$response.StatusCode
} catch {
if($_.Exception.Response){
$status = [int]$_.Exception.Response.StatusCode
} else {
Write-Host ("FAIL (admin) " + $check.Path + ' -> request failed: ' + $_.Exception.Message)
$failed = $true
continue
}
}
if($status -eq $check.Expect){
Write-Host ("OK (admin) " + $check.Path + ' -> ' + $status)
} else {
Write-Host ("FAIL (admin) " + $check.Path + ' -> ' + $status + ' (expected ' + $check.Expect + ')')
$failed = $true
}
}
if($failed){
throw 'Admin smoke test failed - see above'
}
}

Write-Host 'Deploy complete.'

Cargando…
Cancelar
Guardar

Powered by TurnKey Linux.