This commit is contained in:
DanB
2015-11-12 18:10:47 +01:00
11 changed files with 115 additions and 75 deletions

View File

@@ -354,6 +354,7 @@ CREATE TABLE tp_users (
`masked` BOOLEAN NOT NULL,
`attribute_name` varchar(64) NOT NULL,
`attribute_value` varchar(64) NOT NULL,
`weight` DECIMAL(8,2) NOT NULL,
`created_at` TIMESTAMP,
PRIMARY KEY (`id`),
KEY `tpid` (`tpid`)

View File

@@ -349,6 +349,7 @@ CREATE TABLE tp_users (
masked BOOLEAN NOT NULL,
attribute_name VARCHAR(64) NOT NULL,
attribute_value VARCHAR(64) NOT NULL,
weight NUMERIC(8,2) NOT NULL,
created_at TIMESTAMP
);
CREATE INDEX tpusers_tpid_idx ON tp_users (tpid);

View File

@@ -1,19 +1,19 @@
#Tenant[0],UserName[1],Maksed[2],AttributeName[3],AttributeValue[4]
cgrates.org,1001,,SysUserName,danb
cgrates.org,1001,,SysPassword,hisPass321
cgrates.org,1001,,Cli,+4986517174963
cgrates.org,1001,,Account,1001
cgrates.org,1001,,Subject,1001
cgrates.org,1001,,Uuid,388539dfd4f5cefee8f488b78c6c244b9e19138e
cgrates.org,1001,,ReqType,*prepaid
cgrates.org,1002,,SysUserName,rif
cgrates.org,1002,,RifAttr,RifVal
cgrates.org,1002,,Account,1002
cgrates.org,1002,,Subject,1002
cgrates.org,1002,,Uuid,27f37edec0670fa34cf79076b80ef5021e39c5b5
cgrates.org,1004,,SysUserName,danb4
cgrates.org,1004,,SysPassword,hisPass321
cgrates.org,1004,,Cli,+4986517174964
cgrates.org,1004,,Account,1004
cgrates.org,1004,,Subject,1004
cgrates.org,1004,,ReqType,*rated
#Tenant[0],UserName[1],Maksed[2],AttributeName[3],AttributeValue[4],Weight[5]
cgrates.org,1001,,SysUserName,danb,10
cgrates.org,1001,,SysPassword,hisPass321,10
cgrates.org,1001,,Cli,+4986517174963,10
cgrates.org,1001,,Account,1001,10
cgrates.org,1001,,Subject,1001,10
cgrates.org,1001,,Uuid,388539dfd4f5cefee8f488b78c6c244b9e19138e,10
cgrates.org,1001,,ReqType,*prepaid,10
cgrates.org,1002,,SysUserName,rif,10
cgrates.org,1002,,RifAttr,RifVal,10
cgrates.org,1002,,Account,1002,10
cgrates.org,1002,,Subject,1002,10
cgrates.org,1002,,Uuid,27f37edec0670fa34cf79076b80ef5021e39c5b5,10
cgrates.org,1004,,SysUserName,danb4,10
cgrates.org,1004,,SysPassword,hisPass321,10
cgrates.org,1004,,Cli,+4986517174964,10
cgrates.org,1004,,Account,1004,10
cgrates.org,1004,,Subject,1004,10
cgrates.org,1004,,ReqType,*rated,10
1 #Tenant[0] UserName[1] Maksed[2] AttributeName[3] AttributeValue[4] Weight[5]
2 cgrates.org 1001 SysUserName danb 10
3 cgrates.org 1001 SysPassword hisPass321 10
4 cgrates.org 1001 Cli +4986517174963 10
5 cgrates.org 1001 Account 1001 10
6 cgrates.org 1001 Subject 1001 10
7 cgrates.org 1001 Uuid 388539dfd4f5cefee8f488b78c6c244b9e19138e 10
8 cgrates.org 1001 ReqType *prepaid 10
9 cgrates.org 1002 SysUserName rif 10
10 cgrates.org 1002 RifAttr RifVal 10
11 cgrates.org 1002 Account 1002 10
12 cgrates.org 1002 Subject 1002 10
13 cgrates.org 1002 Uuid 27f37edec0670fa34cf79076b80ef5021e39c5b5 10
14 cgrates.org 1004 SysUserName danb4 10
15 cgrates.org 1004 SysPassword hisPass321 10
16 cgrates.org 1004 Cli +4986517174964 10
17 cgrates.org 1004 Account 1004 10
18 cgrates.org 1004 Subject 1004 10
19 cgrates.org 1004 ReqType *rated 10

View File

@@ -1,19 +1,19 @@
#Tenant[0],UserName[1],Masked[2],AttributeName[3],AttributeValue[4]
cgrates.org,1001,,SysUserName,danb
cgrates.org,1001,,SysPassword,hisPass321
cgrates.org,1001,,Cli,+4986517174963
cgrates.org,1001,,Account,1001
cgrates.org,1001,,Subject,1001
cgrates.org,1001,,Uuid,388539dfd4f5cefee8f488b78c6c244b9e19138e
cgrates.org,1001,,ReqType,*prepaid
cgrates.org,1002,,SysUserName,rif
cgrates.org,1002,,RifAttr,RifVal
cgrates.org,1002,,Account,1002
cgrates.org,1002,,Subject,1002
cgrates.org,1002,,Uuid,27f37edec0670fa34cf79076b80ef5021e39c5b5
cgrates.org,1004,,SysUserName,danb4
cgrates.org,1004,,SysPassword,hisPass321
cgrates.org,1004,,Cli,+4986517174964
cgrates.org,1004,,Account,1004
cgrates.org,1004,,Subject,1004
cgrates.org,1004,,ReqType,*rated
#Tenant[0],UserName[1],Masked[2],AttributeName[3],AttributeValue[4],Weight[5]
cgrates.org,1001,,SysUserName,danb,10
cgrates.org,1001,,SysPassword,hisPass321,10
cgrates.org,1001,,Cli,+4986517174963,10
cgrates.org,1001,,Account,1001,10
cgrates.org,1001,,Subject,1001,10
cgrates.org,1001,,Uuid,388539dfd4f5cefee8f488b78c6c244b9e19138e,10
cgrates.org,1001,,ReqType,*prepaid,10
cgrates.org,1002,,SysUserName,rif,10
cgrates.org,1002,,RifAttr,RifVal,10
cgrates.org,1002,,Account,1002,10
cgrates.org,1002,,Subject,1002,10
cgrates.org,1002,,Uuid,27f37edec0670fa34cf79076b80ef5021e39c5b5,10
cgrates.org,1004,,SysUserName,danb4,10
cgrates.org,1004,,SysPassword,hisPass321,10
cgrates.org,1004,,Cli,+4986517174964,10
cgrates.org,1004,,Account,1004,10
cgrates.org,1004,,Subject,1004,10
cgrates.org,1004,,ReqType,*rated,10
1 #Tenant[0] UserName[1] Masked[2] AttributeName[3] AttributeValue[4] Weight[5]
2 cgrates.org 1001 SysUserName danb 10
3 cgrates.org 1001 SysPassword hisPass321 10
4 cgrates.org 1001 Cli +4986517174963 10
5 cgrates.org 1001 Account 1001 10
6 cgrates.org 1001 Subject 1001 10
7 cgrates.org 1001 Uuid 388539dfd4f5cefee8f488b78c6c244b9e19138e 10
8 cgrates.org 1001 ReqType *prepaid 10
9 cgrates.org 1002 SysUserName rif 10
10 cgrates.org 1002 RifAttr RifVal 10
11 cgrates.org 1002 Account 1002 10
12 cgrates.org 1002 Subject 1002 10
13 cgrates.org 1002 Uuid 27f37edec0670fa34cf79076b80ef5021e39c5b5 10
14 cgrates.org 1004 SysUserName danb4 10
15 cgrates.org 1004 SysPassword hisPass321 10
16 cgrates.org 1004 Cli +4986517174964 10
17 cgrates.org 1004 Account 1004 10
18 cgrates.org 1004 Subject 1004 10
19 cgrates.org 1004 ReqType *rated 10

View File

@@ -223,10 +223,10 @@ CDRST2,,,,ACD,,,,,,,,,,,,,,,,,,,,
`
users = `
#Tenant[0],UserName[1],AttributeName[2],AttributeValue[3]
cgrates.org,rif,false,test0,val0
cgrates.org,rif,,test1,val1
cgrates.org,dan,,another,value
cgrates.org,mas,true,another,value
cgrates.org,rif,false,test0,val0,10
cgrates.org,rif,,test1,val1,10
cgrates.org,dan,,another,value,10
cgrates.org,mas,true,another,value,10
`
aliases = `
#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],DestinationId[5],Group[6],Alias[7],Weight[8]

View File

@@ -177,7 +177,7 @@ func APItoModelAction(as *utils.TPActions) (result []TpAction) {
DestinationTags: a.DestinationIds,
RatingSubject: a.RatingSubject,
Categories: a.Categories,
SharedGroups: a.SharedGroups,
SharedGroups: a.SharedGroups,
BalanceWeight: a.BalanceWeight,
ExtraParameters: a.ExtraParameters,
Weight: a.Weight,
@@ -230,7 +230,7 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result []TpActionTrig
BalanceTimingTags: at.BalanceTimingTags,
BalanceRatingSubject: at.BalanceRatingSubject,
BalanceCategories: at.BalanceCategories,
BalanceSharedGroups: at.BalanceSharedGroups,
BalanceSharedGroups: at.BalanceSharedGroups,
BalanceDisabled: at.BalanceDisabled,
MinQueuedItems: at.MinQueuedItems,
ActionsTag: at.ActionsId,
@@ -393,6 +393,7 @@ func APItoModelUsers(attr *utils.TPUsers) (result []TpUser) {
UserName: attr.UserName,
AttributeName: p.AttrName,
AttributeValue: p.AttrValue,
Weight: attr.Weight,
})
}
if len(attr.Profile) == 0 {

View File

@@ -730,6 +730,7 @@ func (tps TpUsers) GetUsers() (map[string]*utils.TPUsers, error) {
user = &utils.TPUsers{
Tenant: tp.Tenant,
UserName: tp.UserName,
Weight: tp.Weight,
}
users[tp.GetId()] = user
}

View File

@@ -162,7 +162,7 @@ type TpAction struct {
Categories string `index:"6" re:""`
DestinationTags string `index:"7" re:"\*any|\w+\s*"`
RatingSubject string `index:"8" re:"\w+\s*"`
SharedGroups string `index:"9" re:"[0-9A-Za-z_;]*"`
SharedGroups string `index:"9" re:"[0-9A-Za-z_;]*"`
ExpiryTime string `index:"10" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
TimingTags string `index:"11" re:"[0-9A-Za-z_;]*|\*any"`
Units float64 `index:"12" re:"\d+\s*"`
@@ -197,7 +197,7 @@ type TpActionTrigger struct {
BalanceCategories string `index:"9" re:""`
BalanceDestinationTags string `index:"10" re:"\w+|\*any"`
BalanceRatingSubject string `index:"11" re:"\w+|\*any"`
BalanceSharedGroups string `index:"12" re:"\w+|\*any"`
BalanceSharedGroups string `index:"12" re:"\w+|\*any"`
BalanceExpiryTime string `index:"13" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
BalanceTimingTags string `index:"14" re:"[0-9A-Za-z_;]*|\*any"`
BalanceWeight float64 `index:"15" re:"\d+\.?\d*"`
@@ -331,11 +331,12 @@ func (t TpCdrstat) TableName() string {
type TpUser struct {
Id int64
Tpid string
Tenant string `index:"0" re:""`
UserName string `index:"1" re:""`
Masked bool `index:"2" re:""`
AttributeName string `index:"3" re:""`
AttributeValue string `index:"4" re:""`
Tenant string `index:"0" re:""`
UserName string `index:"1" re:""`
Masked bool `index:"2" re:""`
AttributeName string `index:"3" re:""`
AttributeValue string `index:"4" re:""`
Weight float64 `index:"5" re:""`
}
func (tu *TpUser) GetId() string {

View File

@@ -15,6 +15,7 @@ type UserProfile struct {
UserName string
Masked bool
Profile map[string]string
Weight float64
ponder int
}
@@ -28,8 +29,9 @@ func (ups UserProfiles) Swap(i, j int) {
ups[i], ups[j] = ups[j], ups[i]
}
func (ups UserProfiles) Less(j, i int) bool { // get higher ponder in front
return ups[i].ponder < ups[j].ponder
func (ups UserProfiles) Less(j, i int) bool { // get higher Weight and ponder in front
return ups[i].Weight < ups[j].Weight ||
(ups[i].Weight == ups[j].Weight && ups[i].ponder < ups[j].ponder)
}
func (ups UserProfiles) Sort() {
@@ -60,9 +62,14 @@ type UserService interface {
ReloadUsers(string, *string) error
}
type prop struct {
masked bool
weight float64
}
type UserMap struct {
table map[string]map[string]string
masked map[string]bool
properties map[string]*prop
index map[string]map[string]bool
indexKeys []string
accountingDb AccountingStorage
@@ -81,7 +88,7 @@ func NewUserMap(accountingDb AccountingStorage, indexes []string) (*UserMap, err
func newUserMap(accountingDb AccountingStorage, indexes []string) *UserMap {
return &UserMap{
table: make(map[string]map[string]string),
masked: make(map[string]bool),
properties: make(map[string]*prop),
index: make(map[string]map[string]bool),
indexKeys: indexes,
accountingDb: accountingDb,
@@ -94,24 +101,22 @@ func (um *UserMap) ReloadUsers(in string, reply *string) error {
// backup old data
oldTable := um.table
oldIndex := um.index
oldMaksed := um.masked
oldProperties := um.properties
um.table = make(map[string]map[string]string)
um.index = make(map[string]map[string]bool)
um.masked = make(map[string]bool)
um.properties = make(map[string]*prop)
// load from db
if ups, err := um.accountingDb.GetUsers(); err == nil {
for _, up := range ups {
um.table[up.GetId()] = up.Profile
if up.Masked {
um.masked[up.GetId()] = true
}
um.properties[up.GetId()] = &prop{weight: up.Weight, masked: up.Masked}
}
} else {
// restore old data before return
um.table = oldTable
um.index = oldIndex
um.masked = oldMaksed
um.properties = oldProperties
*reply = err.Error()
return err
@@ -124,7 +129,7 @@ func (um *UserMap) ReloadUsers(in string, reply *string) error {
utils.Logger.Err(fmt.Sprintf("Error adding %v indexes to user profile service: %v", um.indexKeys, err))
um.table = oldTable
um.index = oldIndex
um.masked = oldMaksed
um.properties = oldProperties
*reply = err.Error()
return err
@@ -142,9 +147,7 @@ func (um *UserMap) SetUser(up UserProfile, reply *string) error {
return err
}
um.table[up.GetId()] = up.Profile
if up.Masked {
um.masked[up.GetId()] = true
}
um.properties[up.GetId()] = &prop{weight: up.Weight, masked: up.Masked}
um.addIndex(&up, um.indexKeys)
*reply = utils.OK
return nil
@@ -158,7 +161,7 @@ func (um *UserMap) RemoveUser(up UserProfile, reply *string) error {
return err
}
delete(um.table, up.GetId())
delete(um.masked, up.GetId())
delete(um.properties, up.GetId())
um.deleteIndex(&up)
*reply = utils.OK
return nil
@@ -172,7 +175,7 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
*reply = utils.ErrNotFound.Error()
return utils.ErrNotFound
}
masked := um.masked[up.GetId()]
properties := um.properties[up.GetId()]
if m == nil {
m = make(map[string]string)
}
@@ -183,7 +186,8 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
oldUp := &UserProfile{
Tenant: up.Tenant,
UserName: up.UserName,
Masked: masked,
Masked: properties.masked,
Weight: properties.weight,
Profile: oldM,
}
for key, value := range up.Profile {
@@ -193,6 +197,7 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
Tenant: up.Tenant,
UserName: up.UserName,
Masked: up.Masked,
Weight: up.Weight,
Profile: m,
}
if err := um.accountingDb.SetUser(finalUp); err != nil {
@@ -200,9 +205,7 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
return err
}
um.table[up.GetId()] = m
if up.Masked == false {
delete(um.masked, up.GetId())
}
um.properties[up.GetId()] = &prop{weight: up.Weight, masked: up.Masked}
um.deleteIndex(oldUp)
um.addIndex(finalUp, um.indexKeys)
*reply = utils.OK
@@ -247,7 +250,7 @@ func (um *UserMap) GetUsers(up UserProfile, results *UserProfiles) error {
candidates := make(UserProfiles, 0) // It should not return nil in case of no users but []
for key, values := range table {
// skip masked if not asked for
if up.Masked == false && um.masked[key] == true {
if up.Masked == false && um.properties[key] != nil && um.properties[key].masked == true {
continue
}
ponder := 0
@@ -283,7 +286,10 @@ func (um *UserMap) GetUsers(up UserProfile, results *UserProfiles) error {
// all filters passed, add to candidates
nup := &UserProfile{
Profile: make(map[string]string),
Masked: um.masked[key],
}
if um.properties[key] != nil {
nup.Masked = um.properties[key].masked
nup.Weight = um.properties[key].weight
}
nup.SetId(key)
nup.ponder = ponder

View File

@@ -17,8 +17,19 @@ var testMap = UserMap{
"test:masked": map[string]string{"t": "v"},
},
index: make(map[string]map[string]bool),
masked: map[string]bool{
"test:masked": true,
properties: map[string]*prop{
"test:masked": &prop{masked: true},
},
}
var testMap2 = UserMap{
table: map[string]map[string]string{
"an:u1": map[string]string{"a": "b", "c": "d"},
"an:u2": map[string]string{"a": "b"},
},
index: make(map[string]map[string]bool),
properties: map[string]*prop{
"an:u2": &prop{weight: 10},
},
}
@@ -304,6 +315,23 @@ func TestUsersGetMissingIdTwoSort(t *testing.T) {
}
}
func TestUsersGetMissingIdTwoSortWeight(t *testing.T) {
up := UserProfile{
Profile: map[string]string{
"a": "b",
"c": "d",
},
}
results := UserProfiles{}
testMap2.GetUsers(up, &results)
if len(results) != 2 {
t.Error("error getting users: ", results)
}
if results[0].GetId() != "an:u2" {
t.Errorf("Error sorting profiles: %+v", results[0])
}
}
func TestUsersAddIndex(t *testing.T) {
var r string
testMap.AddIndex([]string{"t"}, &r)

View File

@@ -345,6 +345,7 @@ type TPUsers struct {
Masked bool
UserName string
Profile []*TPUserProfile
Weight float64
}
type TPUserProfile struct {