First merge from develop to main (WIP) #7
@@ -228,13 +228,13 @@ func (self *Attendance) VerifyCheckinCode(checkinCode string) error {
|
|||||||
|
|
||||||
val, err := Redis.Get(ctx, "checkin_code:"+checkinCode).Result()
|
val, err := Redis.Get(ctx, "checkin_code:"+checkinCode).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("invalid or expired checkin code")
|
return errors.New("[Attendance Data] invalid or expired checkin code")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expected format: user_id:<uuid>:event_id:<uuid>
|
// Expected format: user_id:<uuid>:event_id:<uuid>
|
||||||
parts := strings.Split(val, ":")
|
parts := strings.Split(val, ":")
|
||||||
if len(parts) != 4 {
|
if len(parts) != 4 {
|
||||||
return errors.New("invalid checkin code format")
|
return errors.New("[Attendance Data] invalid checkin code format")
|
||||||
}
|
}
|
||||||
|
|
||||||
userIdStr := parts[1]
|
userIdStr := parts[1]
|
||||||
|
|||||||
@@ -87,5 +87,5 @@ func (self *Client) ValidateRedirectURI(redirectURI string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errors.New("redirect uri not match")
|
return errors.New("[Client Data] redirect uri not match")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func normalizeKey(key []byte) ([]byte, error) {
|
|||||||
case 16, 24, 32:
|
case 16, 24, 32:
|
||||||
return key, nil
|
return key, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("AES key length must be 16, 24, or 32 bytes")
|
return nil, errors.New("[Cryptography AES] AES key length must be 16, 24, or 32 bytes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ func AESGCMDecrypt(encoded string, key []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(data) < gcm.NonceSize() {
|
if len(data) < gcm.NonceSize() {
|
||||||
return nil, errors.New("ciphertext too short")
|
return nil, errors.New("[Cryptography AES] ciphertext too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce := data[:gcm.NonceSize()]
|
nonce := data[:gcm.NonceSize()]
|
||||||
@@ -92,11 +92,11 @@ func pkcs7Pad(data []byte, blockSize int) []byte {
|
|||||||
func pkcs7Unpad(data []byte) ([]byte, error) {
|
func pkcs7Unpad(data []byte) ([]byte, error) {
|
||||||
length := len(data)
|
length := len(data)
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return nil, errors.New("invalid padding")
|
return nil, errors.New("[Cryptography AES] invalid padding")
|
||||||
}
|
}
|
||||||
padding := int(data[length-1])
|
padding := int(data[length-1])
|
||||||
if padding == 0 || padding > length {
|
if padding == 0 || padding > length {
|
||||||
return nil, errors.New("invalid padding")
|
return nil, errors.New("[Cryptography AES] invalid padding")
|
||||||
}
|
}
|
||||||
return data[:length-padding], nil
|
return data[:length-padding], nil
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ func AESCBCDecrypt(encoded string, key []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(data) < block.BlockSize() {
|
if len(data) < block.BlockSize() {
|
||||||
return nil, errors.New("ciphertext too short")
|
return nil, errors.New("[Cryptography AES] ciphertext too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
iv := data[:block.BlockSize()]
|
iv := data[:block.BlockSize()]
|
||||||
@@ -195,7 +195,7 @@ func AESCFBDecrypt(encoded string, key []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(data) < block.BlockSize() {
|
if len(data) < block.BlockSize() {
|
||||||
return nil, errors.New("ciphertext too short")
|
return nil, errors.New("[Cryptography AES] ciphertext too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
iv := data[:block.BlockSize()]
|
iv := data[:block.BlockSize()]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
@@ -17,6 +18,8 @@ func GinLogger() gin.HandlerFunc {
|
|||||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
|
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
headerJSON, _ := json.Marshal(c.Request.Header)
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
c.Next()
|
c.Next()
|
||||||
@@ -33,6 +36,7 @@ func GinLogger() gin.HandlerFunc {
|
|||||||
"ip", c.ClientIP(),
|
"ip", c.ClientIP(),
|
||||||
"latency", time.Since(startTime).String(),
|
"latency", time.Since(startTime).String(),
|
||||||
"user_agent", c.Request.UserAgent(),
|
"user_agent", c.Request.UserAgent(),
|
||||||
|
"headers", string(headerJSON),
|
||||||
"request_body", string(body),
|
"request_body", string(body),
|
||||||
"errors", errorMessage,
|
"errors", errorMessage,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,14 +129,14 @@ func (self *Token) RefreshAccessToken(refreshToken string) (string, error) {
|
|||||||
// read refresh token bind data
|
// read refresh token bind data
|
||||||
dataMap, err := data.Redis.HGetAll(ctx, key).Result()
|
dataMap, err := data.Redis.HGetAll(ctx, key).Result()
|
||||||
if err != nil || len(dataMap) == 0 {
|
if err != nil || len(dataMap) == 0 {
|
||||||
return "", errors.New("invalid refresh token")
|
return "", errors.New("[Auth Token] invalid refresh token")
|
||||||
}
|
}
|
||||||
|
|
||||||
userIdStr := dataMap["user_id"]
|
userIdStr := dataMap["user_id"]
|
||||||
clientId := dataMap["client_id"]
|
clientId := dataMap["client_id"]
|
||||||
|
|
||||||
if userIdStr == "" || clientId == "" {
|
if userIdStr == "" || clientId == "" {
|
||||||
return "", errors.New("refresh token corrupted")
|
return "", errors.New("[Auth Token] refresh token corrupted")
|
||||||
}
|
}
|
||||||
|
|
||||||
userId, err := uuid.Parse(userIdStr)
|
userId, err := uuid.Parse(userIdStr)
|
||||||
@@ -157,14 +157,14 @@ func (self *Token) RenewRefreshToken(refreshToken string) (string, error) {
|
|||||||
// read old refresh token bind data
|
// read old refresh token bind data
|
||||||
dataMap, err := data.Redis.HGetAll(ctx, oldKey).Result()
|
dataMap, err := data.Redis.HGetAll(ctx, oldKey).Result()
|
||||||
if err != nil || len(dataMap) == 0 {
|
if err != nil || len(dataMap) == 0 {
|
||||||
return "", errors.New("invalid refresh token")
|
return "", errors.New("[Auth Token] invalid refresh token")
|
||||||
}
|
}
|
||||||
|
|
||||||
userIdStr := dataMap["user_id"]
|
userIdStr := dataMap["user_id"]
|
||||||
clientId := dataMap["client_id"]
|
clientId := dataMap["client_id"]
|
||||||
|
|
||||||
if userIdStr == "" || clientId == "" {
|
if userIdStr == "" || clientId == "" {
|
||||||
return "", errors.New("refresh token corrupted")
|
return "", errors.New("[Auth Token] refresh token corrupted")
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate new refresh token
|
// generate new refresh token
|
||||||
@@ -254,7 +254,7 @@ func (self *Token) HeaderVerify(header string) (string, error) {
|
|||||||
// Split header to 2
|
// Split header to 2
|
||||||
parts := strings.SplitN(header, " ", 2)
|
parts := strings.SplitN(header, " ", 2)
|
||||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||||
return "", errors.New("invalid Authorization header format")
|
return "", errors.New("[Auth Token] invalid Authorization header format")
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenStr := parts[1]
|
tokenStr := parts[1]
|
||||||
@@ -266,11 +266,11 @@ func (self *Token) HeaderVerify(header string) (string, error) {
|
|||||||
claims,
|
claims,
|
||||||
func(token *jwt.Token) (any, error) {
|
func(token *jwt.Token) (any, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, errors.New("unexpected signing method")
|
return nil, errors.New("[Auth Token] unexpected signing method")
|
||||||
}
|
}
|
||||||
|
|
||||||
if claims.ClientId == "" {
|
if claims.ClientId == "" {
|
||||||
return nil, errors.New("client_id missing in token")
|
return nil, errors.New("[Auth Token] client_id missing in token")
|
||||||
}
|
}
|
||||||
|
|
||||||
clientData, err := new(data.Client).GetClientByClientId(claims.ClientId)
|
clientData, err := new(data.Client).GetClientByClientId(claims.ClientId)
|
||||||
@@ -289,7 +289,7 @@ func (self *Token) HeaderVerify(header string) (string, error) {
|
|||||||
|
|
||||||
if err != nil || !token.Valid {
|
if err != nil || !token.Valid {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return "", errors.New("invalid or expired token")
|
return "", errors.New("[Auth Token] invalid or expired token")
|
||||||
}
|
}
|
||||||
|
|
||||||
return claims.UserID.String(), nil
|
return claims.UserID.String(), nil
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ func (self *Client) NewSMTPClient() (*Client, error) {
|
|||||||
insecure := viper.GetBool("email.insecure_skip_verify")
|
insecure := viper.GetBool("email.insecure_skip_verify")
|
||||||
|
|
||||||
if host == "" || port == 0 || user == "" {
|
if host == "" || port == 0 || user == "" {
|
||||||
return nil, errors.New("SMTP config not set")
|
return nil, errors.New("[Email] SMTP config not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if pass == "" {
|
if pass == "" {
|
||||||
return nil, errors.New("SMTP basic auth requires email.password")
|
return nil, errors.New("[Email] SMTP basic auth requires email.password")
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := gomail.NewDialer(host, port, user, pass)
|
dialer := gomail.NewDialer(host, port, user, pass)
|
||||||
@@ -52,7 +52,7 @@ func (self *Client) NewSMTPClient() (*Client, error) {
|
|||||||
dialer.SSL = false
|
dialer.SSL = false
|
||||||
dialer.TLSConfig = nil
|
dialer.TLSConfig = nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unknown smtp security mode: " + security)
|
return nil, errors.New("[Email] unknown smtp security mode: " + security)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
@@ -67,7 +67,7 @@ func (self *Client) NewSMTPClient() (*Client, error) {
|
|||||||
|
|
||||||
func (c *Client) Send(from, to, subject, html string) (string, error) {
|
func (c *Client) Send(from, to, subject, html string) (string, error) {
|
||||||
if c.dialer == nil {
|
if c.dialer == nil {
|
||||||
return "", errors.New("SMTP dialer not initialized")
|
return "", errors.New("[Email] SMTP dialer not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
m := gomail.NewMessage()
|
m := gomail.NewMessage()
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ import (
|
|||||||
func DecodeB64Json(b64Json string) (*KycInfo, error) {
|
func DecodeB64Json(b64Json string) (*KycInfo, error) {
|
||||||
rawJson, err := base64.StdEncoding.DecodeString(b64Json)
|
rawJson, err := base64.StdEncoding.DecodeString(b64Json)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid base64 json")
|
return nil, errors.New("[KYC] invalid base64 json")
|
||||||
}
|
}
|
||||||
|
|
||||||
var kyc KycInfo
|
var kyc KycInfo
|
||||||
if err := json.Unmarshal(rawJson, &kyc); err != nil {
|
if err := json.Unmarshal(rawJson, &kyc); err != nil {
|
||||||
return nil, errors.New("invalid json structure")
|
return nil, errors.New("[KYC] invalid json structure")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &kyc, nil
|
return &kyc, nil
|
||||||
@@ -56,7 +56,7 @@ func DecodeAES(cipherStr string) (*KycInfo, error) {
|
|||||||
|
|
||||||
var kyc KycInfo
|
var kyc KycInfo
|
||||||
if err := json.Unmarshal(plainBytes, &kyc); err != nil {
|
if err := json.Unmarshal(plainBytes, &kyc); err != nil {
|
||||||
return nil, errors.New("invalid decrypted json")
|
return nil, errors.New("[KYC] invalid decrypted json")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &kyc, nil
|
return &kyc, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user