Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
zgo.at/zvalidate
Simple validation for Go. Some things that make it different from the (many) other libraries:
I originally wrote this at my previous employer (github.com/teamwork/validate), this is an improved (and incompatible) version.
Basic example:
email := "martin@arp42.net"
v := zvalidate.New()
v.Required("email", email)
m := v.Email("email", email)
if v.HasErrors() {
fmt.Printf("Had the following validation errors:\n%s", v)
}
fmt.Printf("parsed email: %s\n", m.Address)
All validators are just method calls on the Validator
struct, and follow the
same patterns:
The input's zero type (empty string, 0, nil, etc.) is valid. Use the
Required()
validator if you want to make a parameter required).
key string, value [..]
are the first two arguments, where key
is the
parameter name (to display in the error or next to a form) and value
is what
we want validated (type of value
depends on validation).
Optionally accept a custom message as the last parameter.
The error text only includes a simple human description such as "must be set" or "must be a valid email". When adding new validations, make sure that they can be displayed properly when joined with commas. A text such as "Error: this field must be higher than 42" would look weird:
must be set, Error: this field must be higher than 42
List of validations with abbreviated function signature (key string, value [..]
omitted):
Function | Description |
---|---|
Required() | Value must not be the type's zero value |
Exclude([]string) | Value is not in the exclude list |
Include([]string) | Value is in the include list |
Range(min, max int) | Minimum and maximum int value. |
Len(min, max int) int | Character length of string |
Integer() int64 | Integer value |
Boolean() bool | Boolean value |
Domain() []string | Domain name; returns list of domain labels. |
URL() *url.URL | Valid URL |
Email() mail.Address | Email address |
IPv4() net.IP | IPv4 address |
IP() net.IP | IPv4 or IPv6 address |
HexColor() (uint8, uint8, uint8) | Colour as hex triplet (#123456 or #123) |
Date(layout string) | Parse according to the given layout |
Phone() string | Looks like a phone number |
You can set your own errors with v.Append():
if !some_complex_condition {
v.Append("foo", "must be a valid foo")
}
Sub()
allows adding nested subvalidations; this is useful if a form creates
more than one object.
For example:
v := zvalidate.New()
v.Sub("settings", -1, customer.Settings.Validate())
This will merge the Validator
object in to v
and prefix all the keys with
settings.
, so you'll have settings.timezone
(instead of just timezone
).
You can also add arrays:
for i, a := range customer.Addresses {
a.Sub("addresses", i, c.Validate())
}
This will be added as addresses[0].city
, addresses[1].city
, etc.
If the error is not a Validator
then the Error()
text will be added as just
the key name without subkey (same as v.Append("key", "msg")
); this is mostly
to support cases like:
func (Customer c) Validate() {
v := validate.New()
ok, err := c.isUniqueEmail(c.Email)
if err != nil {
return err
}
if !ok {
v.Append("email", "must be unique")
}
return v.ErrorOrNil()
}
The Validator
type satisfies the error
interface, so you can return them as
errors; usually you want to return ErrorOrNil()
.
The general idea is that validation errors should usually be displayed along the input element, instead of a list in a flash message (but you can do either).
To display a flash message or CLI just call String()
or HTML()
.
For Go templates there is a TemplateError()
helper which can be added to
the template.FuncMap
. See the godoc for that function for details and an
example.
For JavaScript Errors
is represented as map[string][]string
, and
marshals well to JSON; in your frontend you just have to find the input
belonging to the map key. A simple example might be:
var display_errors = function(errors) {
var hidden = '';
for (var k in errors) {
if (!errors.hasOwnProperty(k))
continue;
var elem = document.querySelector('*[name=' + k + ']')
if (!elem) {
hidden += k + ': ' + errors[k].join(', ');
continue;
}
var err = document.createElement('span');
err.className = 'err';
err.innerHTML = 'Error: ' + errors[k].join(', ') + '.';
elem.insertAdjacentElement('afterend', err);
}
if (hidden !== '')
alert(hidden);
};
display_errors({
'xxx': ['oh noes', 'asd'],
'hidden': ['asd'],
});
caveat: if there is an error with a corresponding form element then that
won't be displayed. This is why the above examples Pop()
all the errors they
want to display, and then display anything that's left. This prevents "hidden"
errors.
There is no direct support for i18n, but the messages are all exported as
Message*
and can be replaced by your i18n system of choice.
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.