revoke.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package certificate
  2. import (
  3. "net/http"
  4. "github.com/0xJacky/Nginx-UI/internal/cert"
  5. "github.com/0xJacky/Nginx-UI/internal/translation"
  6. "github.com/0xJacky/Nginx-UI/query"
  7. "github.com/gin-gonic/gin"
  8. "github.com/gorilla/websocket"
  9. "github.com/spf13/cast"
  10. "github.com/uozi-tech/cosy/logger"
  11. )
  12. type RevokeCertResponse struct {
  13. Status string `json:"status"`
  14. *translation.Container
  15. }
  16. func handleRevokeCertLogChan(conn *websocket.Conn, logChan chan string) {
  17. defer func() {
  18. if err := recover(); err != nil {
  19. logger.Error(err)
  20. }
  21. }()
  22. for logString := range logChan {
  23. err := conn.WriteJSON(RevokeCertResponse{
  24. Status: Info,
  25. Container: translation.C(logString),
  26. })
  27. if err != nil {
  28. logger.Error(err)
  29. return
  30. }
  31. }
  32. }
  33. // RevokeCert handles certificate revocation through websocket connection
  34. func RevokeCert(c *gin.Context) {
  35. id := cast.ToUint64(c.Param("id"))
  36. var upGrader = websocket.Upgrader{
  37. CheckOrigin: func(r *http.Request) bool {
  38. return true
  39. },
  40. }
  41. // upgrade http to websocket
  42. ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
  43. if err != nil {
  44. logger.Error(err)
  45. return
  46. }
  47. defer func(ws *websocket.Conn) {
  48. _ = ws.Close()
  49. }(ws)
  50. // Get certificate from database
  51. certQuery := query.Cert
  52. certModel, err := certQuery.FirstByID(id)
  53. if err != nil {
  54. logger.Error(err)
  55. _ = ws.WriteJSON(RevokeCertResponse{
  56. Status: Error,
  57. Container: translation.C("Certificate not found: %{error}", map[string]any{
  58. "error": err.Error(),
  59. }),
  60. })
  61. return
  62. }
  63. // Create payload for revocation
  64. payload := &cert.ConfigPayload{
  65. CertID: id,
  66. ServerName: certModel.Domains,
  67. ChallengeMethod: certModel.ChallengeMethod,
  68. DNSCredentialID: certModel.DnsCredentialID,
  69. ACMEUserID: certModel.ACMEUserID,
  70. KeyType: certModel.KeyType,
  71. Resource: certModel.Resource,
  72. }
  73. logChan := make(chan string, 1)
  74. errChan := make(chan error, 1)
  75. certLogger := &cert.Logger{}
  76. certLogger.SetWebSocket(ws)
  77. go cert.RevokeCert(payload, certLogger, logChan, errChan)
  78. go handleRevokeCertLogChan(ws, logChan)
  79. // block, until errChan closes
  80. for err = range errChan {
  81. logger.Error(err)
  82. err = ws.WriteJSON(RevokeCertResponse{
  83. Status: Error,
  84. Container: translation.C("Failed to revoke certificate: %{error}", map[string]any{
  85. "error": err.Error(),
  86. }),
  87. })
  88. if err != nil {
  89. logger.Error(err)
  90. return
  91. }
  92. return
  93. }
  94. // Update certificate status in database
  95. err = certModel.Remove()
  96. if err != nil {
  97. logger.Error(err)
  98. _ = ws.WriteJSON(RevokeCertResponse{
  99. Status: Error,
  100. Container: translation.C("Failed to delete certificate from database: %{error}", map[string]any{
  101. "error": err.Error(),
  102. }),
  103. })
  104. return
  105. }
  106. err = ws.WriteJSON(RevokeCertResponse{
  107. Status: Success,
  108. Container: translation.C("Certificate revoked successfully"),
  109. })
  110. if err != nil {
  111. logger.Error(err)
  112. return
  113. }
  114. }