Initial QSfera import
This commit is contained in:
@@ -0,0 +1 @@
|
||||
coverage.txt
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
language: go
|
||||
go:
|
||||
- "1.11"
|
||||
|
||||
env:
|
||||
- env GO111MODULE=on
|
||||
|
||||
script:
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 White Chang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
# Golang Masker
|
||||
|
||||
[](https://travis-ci.org/ggwhite/go-masker)
|
||||
[](https://codecov.io/gh/ggwhite/go-masker)
|
||||
[](https://goreportcard.com/report/github.com/ggwhite/go-masker)
|
||||
[](https://github.com/ggwhite/go-masker/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/ggwhite/go-masker)
|
||||
[](https://github.com/ggwhite/go-masker/releases/latest)
|
||||
|
||||
Golang Masker is a simple utility of creating a mask for sensitive information.
|
||||
|
||||
* [Getting Started](#Getting-Started)
|
||||
|
||||
# Getting Started
|
||||
|
||||
```
|
||||
$ go get -u github.com/ggwhite/go-masker
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
There are two ways to get a masker instance:
|
||||
#### 1. Get a instance directly from go-masker package
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
masker.Name("ggwhite")
|
||||
masker.ID("A123456789")
|
||||
masker.Mobile("0978978978")
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Get a instance via `masker.New()`
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := masker.New()
|
||||
m.Name("ggwhite")
|
||||
m.ID("A123456789")
|
||||
m.Mobile("0978978978")
|
||||
}
|
||||
```
|
||||
|
||||
## Mask Types
|
||||
|
||||
|Type |Const |Tag |Description |
|
||||
|:----------:|:-----------:|:---------:|:------------------------------------------------------------------------------------------------------|
|
||||
|Name |MName |name |mask the second letter and the third letter |
|
||||
|Password |MPassword |password |always return `************` |
|
||||
|Address |MAddress |addr |keep first 6 letters, mask the rest |
|
||||
|Email |MEmail |email |keep domain and the first 3 letters |
|
||||
|Mobile |MMobile |mobile |mask 3 digits from the 4'th digit |
|
||||
|Telephone |MTelephone |tel |remove `(`, `)`, ` `, `-` chart, and mask last 4 digits of telephone number, format to `(??)????-????` |
|
||||
|ID |MID |id |mask last 4 digits of ID number |
|
||||
|CreditCard |MCreditCard |credit |mask 6 digits from the 7'th digit |
|
||||
|Struct |MStruct |struct |mask the struct |
|
||||
|URL |MURL |url |mask the password field if present, eg http://admin:mysecretpassword@localhost:1234/uri |
|
||||
|
||||
## Mask the `String`
|
||||
|
||||
`String` method requires two parameters, a mask type CONST and a string:
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
masker.String(masker.MName, "ggwhite")
|
||||
masker.String(masker.MID, "A123456789")
|
||||
masker.String(masker.MMobile, "0987987987")
|
||||
}
|
||||
```
|
||||
Result:
|
||||
```
|
||||
g**hite
|
||||
A12345****
|
||||
0987***987
|
||||
```
|
||||
|
||||
## Custom Mask
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
masker.String(masker.MName, "ggwhite")
|
||||
masker.String(masker.MID, "A123456789")
|
||||
masker.SetMask("-")
|
||||
masker.String(masker.MMobile, "0987987987")
|
||||
}
|
||||
```
|
||||
Result:
|
||||
```
|
||||
g**hite
|
||||
A12345****
|
||||
0987---987
|
||||
```
|
||||
|
||||
|
||||
## Mask the `Struct`
|
||||
|
||||
You can define your struct and add tag `mask` to let masker know what kind of the format to mask.
|
||||
|
||||
> Field must be **public** in the struct.
|
||||
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
type Foo struct {
|
||||
Name string `mask:"name"`
|
||||
Mobile string `mask:"mobile"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
foo := &Foo{
|
||||
Name: "ggwhite",
|
||||
Mobile: "0987987987",
|
||||
}
|
||||
t, err := masker.Struct(foo)
|
||||
log.Println(t)
|
||||
log.Println(t.(*Foo))
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
Result:
|
||||
```
|
||||
t = &{g**hite 0987***987}
|
||||
err = <nil>
|
||||
```
|
||||
|
||||
### Struct contain struct
|
||||
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
type Foo struct {
|
||||
Name string `mask:"name"`
|
||||
Mobile string `mask:"mobile"`
|
||||
Qoo *Qoo `mask:"struct"`
|
||||
}
|
||||
|
||||
type Qoo struct {
|
||||
Name string `mask:"name"`
|
||||
Telephone string `mask:"tel"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
foo := &Foo{
|
||||
Name: "ggwhite",
|
||||
Mobile: "0987987987",
|
||||
Qoo: &Qoo{
|
||||
Name: "gino",
|
||||
Telephone: "0287658765",
|
||||
},
|
||||
}
|
||||
t, err := masker.Struct(foo)
|
||||
log.Println(t)
|
||||
log.Println(t.(*Foo).Qoo)
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
Result:
|
||||
```
|
||||
t = &{g**hite 0987***987 0xc00000a080}
|
||||
t.Qoo = &{g**o (02)8765-****}
|
||||
err = <nil>
|
||||
```
|
||||
|
||||
### Struct contain string slice
|
||||
``` golang
|
||||
package main
|
||||
|
||||
import (
|
||||
masker "github.com/ggwhite/go-masker"
|
||||
)
|
||||
|
||||
type Foo struct {
|
||||
Name string `mask:"name"`
|
||||
Mobile string `mask:"mobile"`
|
||||
IDs []string `mask:"id"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
foo := &Foo{
|
||||
Name: "ggwhite",
|
||||
Mobile: "0987987987",
|
||||
IDs: []string{
|
||||
"A123456789",
|
||||
"A987654321",
|
||||
},
|
||||
}
|
||||
t, err := masker.Struct(foo)
|
||||
log.Println(t)
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
Result:
|
||||
```
|
||||
t = &{g**hite 0987***987 [A12345**** A98765****]}
|
||||
err = <nil>
|
||||
```
|
||||
+571
@@ -0,0 +1,571 @@
|
||||
// Package masker Provide mask format of Taiwan usually used(Name, Address, Email, ID ...etc.),
|
||||
package masker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const tagName = "mask"
|
||||
|
||||
type mtype string
|
||||
|
||||
// Maske Types of format string
|
||||
const (
|
||||
MPassword mtype = "password"
|
||||
MName mtype = "name"
|
||||
MAddress mtype = "addr"
|
||||
MEmail mtype = "email"
|
||||
MMobile mtype = "mobile"
|
||||
MTelephone mtype = "tel"
|
||||
MID mtype = "id"
|
||||
MCreditCard mtype = "credit"
|
||||
MStruct mtype = "struct"
|
||||
MURL mtype = "url"
|
||||
)
|
||||
|
||||
// Masker is a instance to marshal masked string
|
||||
type Masker struct {
|
||||
mask string
|
||||
}
|
||||
|
||||
func strLoop(str string, length int) string {
|
||||
var mask string
|
||||
for i := 1; i <= length; i++ {
|
||||
mask += str
|
||||
}
|
||||
return mask
|
||||
}
|
||||
|
||||
func (m *Masker) overlay(str string, overlay string, start int, end int) (overlayed string) {
|
||||
r := []rune(str)
|
||||
l := len([]rune(r))
|
||||
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if start > l {
|
||||
start = l
|
||||
}
|
||||
if end < 0 {
|
||||
end = 0
|
||||
}
|
||||
if end > l {
|
||||
end = l
|
||||
}
|
||||
if start > end {
|
||||
tmp := start
|
||||
start = end
|
||||
end = tmp
|
||||
}
|
||||
|
||||
overlayed = ""
|
||||
overlayed += string(r[:start])
|
||||
overlayed += overlay
|
||||
overlayed += string(r[end:])
|
||||
return overlayed
|
||||
}
|
||||
|
||||
// Struct must input a interface{}, add tag mask on struct fields, after Struct(), return a pointer interface{} of input type and it will be masked with the tag format type
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Foo struct {
|
||||
// Name string `mask:"name"`
|
||||
// Email string `mask:"email"`
|
||||
// Password string `mask:"password"`
|
||||
// ID string `mask:"id"`
|
||||
// Address string `mask:"addr"`
|
||||
// Mobile string `mask:"mobile"`
|
||||
// Telephone string `mask:"tel"`
|
||||
// Credit string `mask:"credit"`
|
||||
// Foo *Foo `mask:"struct"`
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// s := &Foo{
|
||||
// Name: ...,
|
||||
// Email: ...,
|
||||
// Password: ...,
|
||||
// Foo: &{
|
||||
// Name: ...,
|
||||
// Email: ...,
|
||||
// Password: ...,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// m := masker.New()
|
||||
//
|
||||
// t, err := m.Struct(s)
|
||||
//
|
||||
// fmt.Println(t.(*Foo))
|
||||
// }
|
||||
func (m *Masker) Struct(s interface{}) (interface{}, error) {
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("input is nil")
|
||||
}
|
||||
|
||||
var selem, tptr reflect.Value
|
||||
|
||||
st := reflect.TypeOf(s)
|
||||
|
||||
if st.Kind() == reflect.Ptr {
|
||||
tptr = reflect.New(st.Elem())
|
||||
selem = reflect.ValueOf(s).Elem()
|
||||
} else {
|
||||
tptr = reflect.New(st)
|
||||
selem = reflect.ValueOf(s)
|
||||
}
|
||||
|
||||
for i := 0; i < selem.NumField(); i++ {
|
||||
if !selem.Type().Field(i).IsExported() {
|
||||
continue
|
||||
}
|
||||
mtag := selem.Type().Field(i).Tag.Get(tagName)
|
||||
if len(mtag) == 0 {
|
||||
tptr.Elem().Field(i).Set(selem.Field(i))
|
||||
continue
|
||||
}
|
||||
switch selem.Field(i).Type().Kind() {
|
||||
default:
|
||||
tptr.Elem().Field(i).Set(selem.Field(i))
|
||||
case reflect.String:
|
||||
tptr.Elem().Field(i).SetString(m.String(mtype(mtag), selem.Field(i).String()))
|
||||
case reflect.Struct:
|
||||
if mtype(mtag) == MStruct {
|
||||
_t, err := m.Struct(selem.Field(i).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tptr.Elem().Field(i).Set(reflect.ValueOf(_t).Elem())
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if selem.Field(i).IsNil() {
|
||||
continue
|
||||
}
|
||||
if mtype(mtag) == MStruct {
|
||||
_t, err := m.Struct(selem.Field(i).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tptr.Elem().Field(i).Set(reflect.ValueOf(_t))
|
||||
}
|
||||
case reflect.Slice:
|
||||
if selem.Field(i).IsNil() {
|
||||
continue
|
||||
}
|
||||
if selem.Field(i).Type().Elem().Kind() == reflect.String {
|
||||
orgval := selem.Field(i).Interface().([]string)
|
||||
newval := make([]string, len(orgval))
|
||||
for i, val := range selem.Field(i).Interface().([]string) {
|
||||
newval[i] = m.String(mtype(mtag), val)
|
||||
}
|
||||
tptr.Elem().Field(i).Set(reflect.ValueOf(newval))
|
||||
continue
|
||||
}
|
||||
if selem.Field(i).Type().Elem().Kind() == reflect.Struct && mtype(mtag) == MStruct {
|
||||
newval := reflect.MakeSlice(selem.Field(i).Type(), 0, selem.Field(i).Len())
|
||||
for j, l := 0, selem.Field(i).Len(); j < l; j++ {
|
||||
_n, err := m.Struct(selem.Field(i).Index(j).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newval = reflect.Append(newval, reflect.ValueOf(_n).Elem())
|
||||
}
|
||||
tptr.Elem().Field(i).Set(newval)
|
||||
continue
|
||||
}
|
||||
if selem.Field(i).Type().Elem().Kind() == reflect.Ptr && mtype(mtag) == MStruct {
|
||||
newval := reflect.MakeSlice(selem.Field(i).Type(), 0, selem.Field(i).Len())
|
||||
for j, l := 0, selem.Field(i).Len(); j < l; j++ {
|
||||
_n, err := m.Struct(selem.Field(i).Index(j).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newval = reflect.Append(newval, reflect.ValueOf(_n))
|
||||
}
|
||||
tptr.Elem().Field(i).Set(newval)
|
||||
continue
|
||||
}
|
||||
if selem.Field(i).Type().Elem().Kind() == reflect.Interface && mtype(mtag) == MStruct {
|
||||
newval := reflect.MakeSlice(selem.Field(i).Type(), 0, selem.Field(i).Len())
|
||||
for j, l := 0, selem.Field(i).Len(); j < l; j++ {
|
||||
_n, err := m.Struct(selem.Field(i).Index(j).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reflect.TypeOf(selem.Field(i).Index(j).Interface()).Kind() != reflect.Ptr {
|
||||
newval = reflect.Append(newval, reflect.ValueOf(_n).Elem())
|
||||
} else {
|
||||
newval = reflect.Append(newval, reflect.ValueOf(_n))
|
||||
}
|
||||
}
|
||||
tptr.Elem().Field(i).Set(newval)
|
||||
continue
|
||||
}
|
||||
case reflect.Interface:
|
||||
if selem.Field(i).IsNil() {
|
||||
continue
|
||||
}
|
||||
if mtype(mtag) != MStruct {
|
||||
continue
|
||||
}
|
||||
_t, err := m.Struct(selem.Field(i).Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reflect.TypeOf(selem.Field(i).Interface()).Kind() != reflect.Ptr {
|
||||
tptr.Elem().Field(i).Set(reflect.ValueOf(_t).Elem())
|
||||
} else {
|
||||
tptr.Elem().Field(i).Set(reflect.ValueOf(_t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tptr.Interface(), nil
|
||||
}
|
||||
|
||||
// String mask input string of the mask type
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// masker.String(masker.MName, "ggwhite")
|
||||
// masker.String(masker.MID, "A123456789")
|
||||
// masker.String(masker.MMobile, "0987987987")
|
||||
func (m *Masker) String(t mtype, i string) string {
|
||||
switch t {
|
||||
default:
|
||||
return i
|
||||
case MPassword:
|
||||
return m.Password(i)
|
||||
case MName:
|
||||
return m.Name(i)
|
||||
case MAddress:
|
||||
return m.Address(i)
|
||||
case MEmail:
|
||||
return m.Email(i)
|
||||
case MMobile:
|
||||
return m.Mobile(i)
|
||||
case MID:
|
||||
return m.ID(i)
|
||||
case MTelephone:
|
||||
return m.Telephone(i)
|
||||
case MCreditCard:
|
||||
return m.CreditCard(i)
|
||||
case MURL:
|
||||
return m.URL(i)
|
||||
}
|
||||
}
|
||||
|
||||
// Name mask the second letter and the third letter
|
||||
//
|
||||
// Example:
|
||||
// input: ABCD
|
||||
// output: A**D
|
||||
func (m *Masker) Name(i string) string {
|
||||
l := len([]rune(i))
|
||||
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// if has space
|
||||
if strs := strings.Split(i, " "); len(strs) > 1 {
|
||||
tmp := make([]string, len(strs))
|
||||
for idx, str := range strs {
|
||||
tmp[idx] = m.Name(str)
|
||||
}
|
||||
return strings.Join(tmp, " ")
|
||||
}
|
||||
|
||||
if l == 2 || l == 3 {
|
||||
return m.overlay(i, strLoop(instance.mask, len("**")), 1, 2)
|
||||
}
|
||||
|
||||
if l > 3 {
|
||||
return m.overlay(i, strLoop(instance.mask, len("**")), 1, 3)
|
||||
}
|
||||
|
||||
return strLoop(instance.mask, len("**"))
|
||||
}
|
||||
|
||||
// ID mask last 4 digits of ID number
|
||||
//
|
||||
// Example:
|
||||
// input: A123456789
|
||||
// output: A12345****
|
||||
func (m *Masker) ID(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
return m.overlay(i, strLoop(instance.mask, len("****")), 6, 10)
|
||||
}
|
||||
|
||||
// Address keep first 6 letters, mask the rest
|
||||
//
|
||||
// Example:
|
||||
// input: 台北市內湖區內湖路一段737巷1號1樓
|
||||
// output: 台北市內湖區******
|
||||
func (m *Masker) Address(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
if l <= 6 {
|
||||
return strLoop(instance.mask, len("******"))
|
||||
}
|
||||
return m.overlay(i, strLoop(instance.mask, len("******")), 6, math.MaxInt)
|
||||
}
|
||||
|
||||
// CreditCard mask 6 digits from the 7'th digit
|
||||
//
|
||||
// Example:
|
||||
// input1: 1234567890123456 (VISA, JCB, MasterCard)(len = 16)
|
||||
// output1: 123456******3456
|
||||
// input2: 123456789012345` (American Express)(len = 15)
|
||||
// output2: 123456******345`
|
||||
func (m *Masker) CreditCard(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
return m.overlay(i, strLoop(instance.mask, len("******")), 6, 12)
|
||||
}
|
||||
|
||||
// Email keep domain and the first 3 letters
|
||||
//
|
||||
// Example:
|
||||
// input: ggw.chang@gmail.com
|
||||
// output: ggw****@gmail.com
|
||||
func (m *Masker) Email(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
tmp := strings.Split(i, "@")
|
||||
if len(tmp) == 1 {
|
||||
return m.overlay(i, strLoop(instance.mask, len("****")), 3, 7)
|
||||
}
|
||||
|
||||
addr := tmp[0]
|
||||
domain := tmp[1]
|
||||
|
||||
addr = m.overlay(addr, strLoop(instance.mask, len("****")), 3, 7)
|
||||
|
||||
return addr + "@" + domain
|
||||
}
|
||||
|
||||
// Mobile mask 3 digits from the 4'th digit
|
||||
//
|
||||
// Example:
|
||||
// input: 0987654321
|
||||
// output: 0987***321
|
||||
func (m *Masker) Mobile(i string) string {
|
||||
if len(i) == 0 {
|
||||
return ""
|
||||
}
|
||||
return m.overlay(i, strLoop(instance.mask, len("***")), 4, 7)
|
||||
}
|
||||
|
||||
// Telephone remove "(", ")", " ", "-" chart, and mask last 4 digits of telephone number, format to "(??)????-????"
|
||||
//
|
||||
// Example:
|
||||
// input: 0227993078
|
||||
// output: (02)2799-****
|
||||
func (m *Masker) Telephone(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
i = strings.Replace(i, " ", "", -1)
|
||||
i = strings.Replace(i, "(", "", -1)
|
||||
i = strings.Replace(i, ")", "", -1)
|
||||
i = strings.Replace(i, "-", "", -1)
|
||||
|
||||
l = len([]rune(i))
|
||||
|
||||
if l != 10 && l != 8 {
|
||||
return i
|
||||
}
|
||||
|
||||
ans := ""
|
||||
|
||||
if l == 10 {
|
||||
ans += "("
|
||||
ans += i[:2]
|
||||
ans += ")"
|
||||
i = i[2:]
|
||||
}
|
||||
|
||||
ans += i[:4]
|
||||
ans += "-"
|
||||
ans += "****"
|
||||
|
||||
return ans
|
||||
}
|
||||
|
||||
// Password always return "************"
|
||||
func (m *Masker) Password(i string) string {
|
||||
l := len([]rune(i))
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
return strLoop(instance.mask, len("************"))
|
||||
}
|
||||
|
||||
// URL mask the password part of the URL if exists
|
||||
//
|
||||
// Example:
|
||||
// input: http://admin:mysecretpassword@localhost:1234/uri
|
||||
// output:http://admin:xxxxx@localhost:1234/uri
|
||||
func (m *Masker) URL(i string) string {
|
||||
u, err := url.Parse(i)
|
||||
if err != nil {
|
||||
return i
|
||||
}
|
||||
return u.Redacted()
|
||||
}
|
||||
|
||||
// New create Masker
|
||||
func New() *Masker {
|
||||
return &Masker{
|
||||
mask: "*",
|
||||
}
|
||||
}
|
||||
|
||||
var instance *Masker
|
||||
|
||||
func init() {
|
||||
instance = New()
|
||||
}
|
||||
|
||||
// Struct must input a interface{}, add tag mask on struct fields, after Struct(), return a pointer interface{} of input type and it will be masked with the tag format type
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Foo struct {
|
||||
// Name string `mask:"name"`
|
||||
// Email string `mask:"email"`
|
||||
// Password string `mask:"password"`
|
||||
// ID string `mask:"id"`
|
||||
// Address string `mask:"addr"`
|
||||
// Mobile string `mask:"mobile"`
|
||||
// Telephone string `mask:"tel"`
|
||||
// Credit string `mask:"credit"`
|
||||
// Foo *Foo `mask:"struct"`
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// s := &Foo{
|
||||
// Name: ...,
|
||||
// Email: ...,
|
||||
// Password: ...,
|
||||
// Foo: &{
|
||||
// Name: ...,
|
||||
// Email: ...,
|
||||
// Password: ...,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// t, err := masker.Struct(s)
|
||||
//
|
||||
// fmt.Println(t.(*Foo))
|
||||
// }
|
||||
func Struct(s interface{}) (interface{}, error) {
|
||||
return instance.Struct(s)
|
||||
}
|
||||
|
||||
// String mask input string of the mask type
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// masker.String(masker.MName, "ggwhite")
|
||||
// masker.String(masker.MID, "A123456789")
|
||||
// masker.String(masker.MMobile, "0987987987")
|
||||
func String(t mtype, i string) string {
|
||||
return instance.String(t, i)
|
||||
}
|
||||
|
||||
// Name mask the second letter and the third letter
|
||||
//
|
||||
// Example:
|
||||
// input: ABCD
|
||||
// output: A**D
|
||||
func Name(i string) string {
|
||||
return instance.Name(i)
|
||||
}
|
||||
|
||||
// ID mask last 4 digits of ID number
|
||||
//
|
||||
// Example:
|
||||
// input: A123456789
|
||||
// output: A12345****
|
||||
func ID(i string) string {
|
||||
return instance.ID(i)
|
||||
}
|
||||
|
||||
// Address keep first 6 letters, mask the rest
|
||||
//
|
||||
// Example:
|
||||
// input: 台北市內湖區內湖路一段737巷1號1樓
|
||||
// output: 台北市內湖區******
|
||||
func Address(i string) string {
|
||||
return instance.Address(i)
|
||||
}
|
||||
|
||||
// CreditCard mask 6 digits from the 7'th digit
|
||||
//
|
||||
// Example:
|
||||
// input1: 1234567890123456 (VISA, JCB, MasterCard)(len = 16)
|
||||
// output1: 123456******3456
|
||||
// input2: 123456789012345 (American Express)(len = 15)
|
||||
// output2: 123456******345
|
||||
func CreditCard(i string) string {
|
||||
return instance.CreditCard(i)
|
||||
}
|
||||
|
||||
// Email keep domain and the first 3 letters
|
||||
//
|
||||
// Example:
|
||||
// input: ggw.chang@gmail.com
|
||||
// output: ggw****@gmail.com
|
||||
func Email(i string) string {
|
||||
return instance.Email(i)
|
||||
}
|
||||
|
||||
// Mobile mask 3 digits from the 4'th digit
|
||||
//
|
||||
// Example:
|
||||
// input: 0987654321
|
||||
// output: 0987***321
|
||||
func Mobile(i string) string {
|
||||
return instance.Mobile(i)
|
||||
}
|
||||
|
||||
// Telephone remove "(", ")", " ", "-" chart, and mask last 4 digits of telephone number, format to "(??)????-????"
|
||||
//
|
||||
// Example:
|
||||
// input: 0227993078
|
||||
// output: (02)2799-****
|
||||
func Telephone(i string) string {
|
||||
return instance.Telephone(i)
|
||||
}
|
||||
|
||||
// Password always return "************"
|
||||
func Password(i string) string {
|
||||
return instance.Password(i)
|
||||
}
|
||||
|
||||
func SetMask(mask string) {
|
||||
instance.mask = mask
|
||||
}
|
||||
Reference in New Issue
Block a user