Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -9,8 +9,9 @@ func (m *GraphMailer) SendPasswordResetMail(toEmail string, resetURL string) err
|
|||||||
<p>Merhaba,</p>
|
<p>Merhaba,</p>
|
||||||
<p>Parolanızı sıfırlamak için aşağıdaki bağlantıya tıklayın:</p>
|
<p>Parolanızı sıfırlamak için aşağıdaki bağlantıya tıklayın:</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="%s">%s</a>
|
<a href="%s">Parolayı sıfırla</a>
|
||||||
</p>
|
</p>
|
||||||
|
<p style="font-size:12px;color:#666;">Bağlantı: %s</p>
|
||||||
<p>Bu bağlantı <strong>30 dakika</strong> geçerlidir ve tek kullanımlıktır.</p>
|
<p>Bu bağlantı <strong>30 dakika</strong> geçerlidir ve tek kullanımlıktır.</p>
|
||||||
`, resetURL, resetURL)
|
`, resetURL, resetURL)
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,28 @@ package security
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildResetURL(token string) string {
|
func BuildResetURL(token string) string {
|
||||||
base := os.Getenv("FRONTEND_URL")
|
base := os.Getenv("APP_FRONTEND_URL")
|
||||||
|
if base == "" {
|
||||||
|
base = os.Getenv("FRONTEND_URL")
|
||||||
|
}
|
||||||
if base == "" {
|
if base == "" {
|
||||||
base = "http://localhost:9000"
|
base = "http://localhost:9000"
|
||||||
}
|
}
|
||||||
|
base = strings.TrimRight(base, "/")
|
||||||
|
// If base already points to password-reset, just append token if needed.
|
||||||
|
if strings.Contains(base, "/password-reset") {
|
||||||
|
if strings.HasSuffix(base, "/password-reset") || strings.HasSuffix(base, "/password-reset/") ||
|
||||||
|
strings.HasSuffix(base, "/#/password-reset") || strings.HasSuffix(base, "/#/password-reset/") {
|
||||||
|
return strings.TrimRight(base, "/") + "/" + token
|
||||||
|
}
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
if strings.Contains(base, "#") {
|
||||||
return base + "/password-reset/" + token
|
return base + "/password-reset/" + token
|
||||||
|
}
|
||||||
|
return base + "/#/password-reset/" + token
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import (
|
|||||||
"bssapp-backend/internal/security"
|
"bssapp-backend/internal/security"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -84,11 +82,7 @@ func ForgotPasswordHandler(
|
|||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
// 5️⃣ Reset URL (PLAIN token)
|
// 5️⃣ Reset URL (PLAIN token)
|
||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
resetURL := fmt.Sprintf(
|
resetURL := security.BuildResetURL(plain)
|
||||||
"%s/password-reset/%s",
|
|
||||||
os.Getenv("FRONTEND_URL"),
|
|
||||||
plain,
|
|
||||||
)
|
|
||||||
|
|
||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
// 6️⃣ Mail gönder (fail olsa bile enumeration yok)
|
// 6️⃣ Mail gönder (fail olsa bile enumeration yok)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -462,11 +461,7 @@ func SendPasswordResetMailHandler(
|
|||||||
`, userID, hash, expires)
|
`, userID, hash, expires)
|
||||||
|
|
||||||
// 🔗 URL → PLAIN
|
// 🔗 URL → PLAIN
|
||||||
resetURL := fmt.Sprintf(
|
resetURL := security.BuildResetURL(plain)
|
||||||
"%s/password-reset/%s",
|
|
||||||
os.Getenv("FRONTEND_URL"),
|
|
||||||
plain,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = mailer.SendPasswordResetMail(email, resetURL)
|
_ = mailer.SendPasswordResetMail(email, resetURL)
|
||||||
|
|
||||||
|
|||||||
@@ -2533,6 +2533,50 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
|||||||
console.log(`🧭 Order mode set edildi → ${mode}`)
|
console.log(`🧭 Order mode set edildi → ${mode}`)
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
// Sync only header-related fields from the form before submit.
|
||||||
|
syncHeaderFromForm(form) {
|
||||||
|
if (!form || typeof form !== 'object') return
|
||||||
|
|
||||||
|
const keys = [
|
||||||
|
'OrderHeaderID',
|
||||||
|
'OrderTypeCode',
|
||||||
|
'ProcessCode',
|
||||||
|
'OrderNumber',
|
||||||
|
'OrderDate',
|
||||||
|
'AverageDueDate',
|
||||||
|
'Description',
|
||||||
|
'InternalDescription',
|
||||||
|
'CurrAccTypeCode',
|
||||||
|
'CurrAccCode',
|
||||||
|
'CurrAccDescription',
|
||||||
|
'DocCurrencyCode',
|
||||||
|
'LocalCurrencyCode',
|
||||||
|
'ExchangeRate',
|
||||||
|
'OfficeCode',
|
||||||
|
'CreatedUserName',
|
||||||
|
'CreatedDate',
|
||||||
|
'LastUpdatedUserName',
|
||||||
|
'LastUpdatedDate',
|
||||||
|
'PaymentTerm',
|
||||||
|
'WarehouseCode',
|
||||||
|
'StoreCode'
|
||||||
|
]
|
||||||
|
|
||||||
|
const patch = {}
|
||||||
|
for (const k of keys) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(form, k)) {
|
||||||
|
patch[k] = form[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(patch).length > 0) {
|
||||||
|
this.header = {
|
||||||
|
...(this.header || {}),
|
||||||
|
...patch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
/* ===========================================================
|
/* ===========================================================
|
||||||
🟦 submitAllReal (v12.1c — FINAL / CLEAN + PRE-VALIDATE)
|
🟦 submitAllReal (v12.1c — FINAL / CLEAN + PRE-VALIDATE)
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
@@ -2553,6 +2597,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
|||||||
// 🔒 Kontrollü submit → route leave guard susar
|
// 🔒 Kontrollü submit → route leave guard susar
|
||||||
this.isControlledSubmit = true
|
this.isControlledSubmit = true
|
||||||
|
|
||||||
|
// ✅ Formdaki header alanlarını store'a taşı
|
||||||
|
this.syncHeaderFromForm?.(form)
|
||||||
|
|
||||||
const isNew = this.mode === 'new'
|
const isNew = this.mode === 'new'
|
||||||
const { header, lines } = this.buildFinalOrderJson()
|
const { header, lines } = this.buildFinalOrderJson()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user