Implement user password checking
This commit is contained in:
parent
8e2d2cce3e
commit
996ecb9f80
25 changed files with 10762 additions and 224 deletions
|
|
@ -2,52 +2,29 @@ package phpx
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PHPBoolean represents a boolean php value.
|
||||
// Boolean represents a boolean php value.
|
||||
//
|
||||
// The value can be marshaled to and from php and will behave as a PHP would behave.
|
||||
//
|
||||
// The value will always be marshaled as "true" or "false".
|
||||
// Unmarshaling uses [Boolean].
|
||||
type PHPBoolean bool
|
||||
// Unmarshaling uses [AsBoolean].
|
||||
type Boolean bool
|
||||
|
||||
func (bi PHPBoolean) MarshalJSON() ([]byte, error) {
|
||||
if bi {
|
||||
return []byte("true"), nil
|
||||
}
|
||||
return []byte("false"), nil
|
||||
}
|
||||
func (bi *PHPBoolean) UnmarshalJSON(data []byte) (err error) {
|
||||
// unmarshal into a generic value
|
||||
var value any
|
||||
err = json.Unmarshal(data, &value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// cast into a boolean
|
||||
cast, ok := Boolean(value)
|
||||
if !ok {
|
||||
value = false
|
||||
}
|
||||
*bi = PHPBoolean(cast)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Boolean tries to cast the given value to a boolean.
|
||||
// AsBoolean tries to cast the given value to a boolean.
|
||||
//
|
||||
// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value.
|
||||
// Value treates all values as the boolean true, except for the ones listed at [doc].
|
||||
//
|
||||
// [doc]: https://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting
|
||||
func Boolean(value any) (b bool, ok bool) {
|
||||
func AsBoolean(value any) (b Boolean, ok bool) {
|
||||
switch d := value.(type) {
|
||||
case bool:
|
||||
return d, true
|
||||
return Boolean(d), true
|
||||
case float64:
|
||||
return d != 0, true
|
||||
case string:
|
||||
|
|
@ -62,13 +39,40 @@ func Boolean(value any) (b bool, ok bool) {
|
|||
return true, false
|
||||
}
|
||||
|
||||
// String tries to cast the given value to a string.
|
||||
func (b Boolean) MarshalJSON() ([]byte, error) {
|
||||
if b {
|
||||
return []byte("true"), nil
|
||||
}
|
||||
return []byte("false"), nil
|
||||
}
|
||||
|
||||
var errNotABoolean = errors.New("Boolean.UnmarshalJSON: Not an integer")
|
||||
|
||||
func (b *Boolean) UnmarshalJSON(data []byte) (err error) {
|
||||
return UnmarshalIntermediate(b, func(a any) (Boolean, error) {
|
||||
b, ok := AsBoolean(a)
|
||||
if !ok {
|
||||
return Boolean(false), errNotABoolean
|
||||
}
|
||||
return b, nil
|
||||
}, data)
|
||||
}
|
||||
|
||||
// String represents a string php value.
|
||||
//
|
||||
// The value can be marshaled to and from php and will behave as a PHP would behave.
|
||||
//
|
||||
// The value will always be marshaled as a literal string.
|
||||
// Unmarshaling uses [AsString].
|
||||
type String string
|
||||
|
||||
// AsString tries to cast the given value to a string.
|
||||
//
|
||||
// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value.
|
||||
// Value casting is described at [doc].
|
||||
//
|
||||
// [doc]: https://www.php.net/manual/en/language.types.string.php#language.types.string.casting
|
||||
func String(value any) (s string, ok bool) {
|
||||
func AsString(value any) (s String, ok bool) {
|
||||
switch d := value.(type) {
|
||||
case bool:
|
||||
if d {
|
||||
|
|
@ -77,13 +81,12 @@ func String(value any) (s string, ok bool) {
|
|||
return "", true
|
||||
case float64:
|
||||
if d == float64(int64(d)) {
|
||||
return strconv.FormatInt(int64(d), 10), true
|
||||
return String(strconv.FormatInt(int64(d), 10)), true
|
||||
}
|
||||
// TODO: not sure this is entirely correct
|
||||
// and we should handle ints here!
|
||||
return strconv.FormatFloat(d, 'E', 1, 64), true
|
||||
return String(strconv.FormatFloat(d, 'E', 1, 64)), true
|
||||
case string:
|
||||
return d, true
|
||||
return String(d), true
|
||||
case []any, map[string]any:
|
||||
return "Array", true
|
||||
case nil:
|
||||
|
|
@ -93,14 +96,38 @@ func String(value any) (s string, ok bool) {
|
|||
return "", false
|
||||
}
|
||||
|
||||
// Integer tries to cast the given value to an integer.
|
||||
func (s String) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(string(s))
|
||||
}
|
||||
|
||||
var errNotAString = errors.New("String.UnmarshalJSON: Not a string")
|
||||
|
||||
func (s *String) UnmarshalJSON(data []byte) (err error) {
|
||||
return UnmarshalIntermediate(s, func(a any) (String, error) {
|
||||
s, ok := AsString(a)
|
||||
if !ok {
|
||||
return s, errNotAString
|
||||
}
|
||||
return s, nil
|
||||
}, data)
|
||||
}
|
||||
|
||||
// Integer represents a boolean integer value.
|
||||
//
|
||||
// The value can be marshaled to and from php and will behave as a PHP would behave.
|
||||
//
|
||||
// The value will always be marshaled as an integer directly
|
||||
// Unmarshaling uses [AsInteger].
|
||||
type Integer int64
|
||||
|
||||
// AsInteger tries to cast the given value to an integer.
|
||||
//
|
||||
// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value.
|
||||
// Value casting is described at [doc].
|
||||
//
|
||||
// [doc]: https://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting
|
||||
func Integer(value any) (i int64, ok bool) {
|
||||
str, ok := String(value)
|
||||
func AsInteger(value any) (i Integer, ok bool) {
|
||||
str, ok := AsString(value)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
|
|
@ -108,31 +135,62 @@ func Integer(value any) (i int64, ok bool) {
|
|||
// try to parse the "leading" string, by successively cutting off parts of the tail
|
||||
// once we have a valid number, return it.
|
||||
for l := 0; l < len(str); l++ {
|
||||
i64, err := strconv.ParseInt(str[:len(str)-l], 10, 64)
|
||||
i64, err := strconv.ParseInt(string(str)[:len(str)-l], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return i64, true
|
||||
return Integer(i64), true
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
|
||||
// TimeInt represents a time value in PHP, represented as an integer
|
||||
type TimeInt time.Time
|
||||
func (i Integer) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(int64(i))
|
||||
}
|
||||
|
||||
func (ts TimeInt) Time() time.Time {
|
||||
var errNotAnInteger = errors.New("Integer.UnmarshalJSON: Not an integer")
|
||||
|
||||
func (i *Integer) UnmarshalJSON(data []byte) (err error) {
|
||||
return UnmarshalIntermediate(i, func(a any) (Integer, error) {
|
||||
i, ok := AsInteger(a)
|
||||
if !ok {
|
||||
return i, errNotAnInteger
|
||||
}
|
||||
return i, nil
|
||||
}, data)
|
||||
}
|
||||
|
||||
// Timestamp represents a time value in PHP, represented as an integer
|
||||
type Timestamp time.Time
|
||||
|
||||
func (ts Timestamp) Time() time.Time {
|
||||
return time.Time(ts)
|
||||
}
|
||||
func (ts TimeInt) MarshalJSON() ([]byte, error) {
|
||||
func (ts Timestamp) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.FormatInt(ts.Time().Unix(), 10)), nil
|
||||
}
|
||||
|
||||
func (ts *TimeInt) UnmarshalJSON(data []byte) (err error) {
|
||||
var value any
|
||||
if err := json.Unmarshal(data, &value); err != nil {
|
||||
func (ts *Timestamp) UnmarshalJSON(data []byte) (err error) {
|
||||
return UnmarshalIntermediate(ts, func(value Integer) (Timestamp, error) {
|
||||
return Timestamp(time.Unix(int64(value), 0)), nil
|
||||
}, data)
|
||||
}
|
||||
|
||||
// UnmarshalIntermediate unmarshals src into dest using an intermediate value of type I.
|
||||
//
|
||||
// It first unmarshals src into a new value of type I.
|
||||
// It then calls parser to parse I into T.
|
||||
func UnmarshalIntermediate[I, T any](dest *T, parser func(I) (T, error), src []byte) (err error) {
|
||||
var temp I
|
||||
err = json.Unmarshal(src, &temp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unix, _ := Integer(value)
|
||||
*ts = TimeInt(time.Unix(unix, 0))
|
||||
|
||||
*dest, err = parser(temp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue