diff --git a/apier/v1/auth.go b/apier/v1/auth.go index 0b548da60..d0ef5e8b3 100644 --- a/apier/v1/auth.go +++ b/apier/v1/auth.go @@ -28,6 +28,11 @@ import ( // Returns MaxUsage (for calls in seconds), -1 for no limit func (self *ApierV1) GetMaxUsage(usageRecord engine.UsageRecord, maxUsage *float64) error { + out, err := engine.LoadUserProfile(usageRecord, "") + if err != nil { + return err + } + usageRecord = out.(engine.UsageRecord) if usageRecord.TOR == "" { usageRecord.TOR = utils.VOICE } diff --git a/apier/v1/cdrsv1.go b/apier/v1/cdrsv1.go index afa46d850..6cadcb9e2 100644 --- a/apier/v1/cdrsv1.go +++ b/apier/v1/cdrsv1.go @@ -41,6 +41,12 @@ func (self *CdrsV1) ProcessCdr(cdr *engine.StoredCdr, reply *string) error { // Designed for external programs feeding CDRs to CGRateS func (self *CdrsV1) ProcessExternalCdr(cdr *engine.ExternalCdr, reply *string) error { + out, err := engine.LoadUserProfile(cdr, "ExtraFields") + if err != nil { + *reply = err.Error() + return err + } + *cdr = out.(engine.ExternalCdr) if err := self.CdrSrv.ProcessExternalCdr(cdr); err != nil { return utils.NewErrServerError(err) } diff --git a/apier/v1/debit.go b/apier/v1/debit.go index 321dab63a..9daf87fd1 100644 --- a/apier/v1/debit.go +++ b/apier/v1/debit.go @@ -27,6 +27,12 @@ func (self *ApierV1) DebitUsage(usageRecord engine.UsageRecord, reply *string) e if missing := utils.MissingStructFields(&usageRecord, []string{"Account", "Destination", "Usage"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } + out, err := engine.LoadUserProfile(usageRecord, "") + if err != nil { + *reply = err.Error() + return err + } + usageRecord = out.(engine.UsageRecord) if usageRecord.TOR == "" { usageRecord.TOR = utils.VOICE } diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index cb3312c41..6301ce4e2 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -77,9 +77,11 @@ func executeCommand(command string) { } if cmd.RpcMethod() != "" { res := cmd.RpcResult() - param := cmd.RpcParams(true, false) + param := cmd.RpcParams(false) //log.Print(reflect.TypeOf(param)) switch param.(type) { + case *console.EmptyWrapper: + param = "" case *console.StringWrapper: param = param.(*console.StringWrapper).Item case *console.StringSliceWrapper: diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 88d700249..5b60033f2 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -541,7 +541,7 @@ func main() { return } } - //engine.SetPubSub(users) + engine.SetUserService(userServer) }() wg.Wait() diff --git a/console/account_add.go b/console/account_add.go index 660be2ff6..315caa1b6 100644 --- a/console/account_add.go +++ b/console/account_add.go @@ -45,14 +45,11 @@ func (self *CmdAddAccount) RpcMethod() string { return self.rpcMethod } -func (self *CmdAddAccount) RpcParams(ptr, reset bool) interface{} { +func (self *CmdAddAccount) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrSetAccount{Direction: utils.OUT} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdAddAccount) PostprocessRpcParams() error { diff --git a/console/account_remove.go b/console/account_remove.go index 22e516038..10380d32f 100644 --- a/console/account_remove.go +++ b/console/account_remove.go @@ -45,14 +45,11 @@ func (self *CmdRemoveAccount) RpcMethod() string { return self.rpcMethod } -func (self *CmdRemoveAccount) RpcParams(ptr, reset bool) interface{} { +func (self *CmdRemoveAccount) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrRemoveAccount{Direction: utils.OUT} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdRemoveAccount) PostprocessRpcParams() error { diff --git a/console/accountactions_set.go b/console/accountactions_set.go index 75b757c39..69e54bd10 100644 --- a/console/accountactions_set.go +++ b/console/accountactions_set.go @@ -45,14 +45,11 @@ func (self *CmdSetAccountActions) RpcMethod() string { return self.rpcMethod } -func (self *CmdSetAccountActions) RpcParams(ptr, reset bool) interface{} { +func (self *CmdSetAccountActions) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.TPAccountActions{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdSetAccountActions) PostprocessRpcParams() error { diff --git a/console/accounts.go b/console/accounts.go index a4e2f32eb..79fdf6beb 100644 --- a/console/accounts.go +++ b/console/accounts.go @@ -49,14 +49,11 @@ func (self *CmdGetAccounts) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetAccounts) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetAccounts) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrGetAccounts{Direction: "*out"} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetAccounts) PostprocessRpcParams() error { diff --git a/console/action_execute.go b/console/action_execute.go index f2f22da9c..15ee3838c 100644 --- a/console/action_execute.go +++ b/console/action_execute.go @@ -48,14 +48,11 @@ func (self *CmdExecuteAction) RpcMethod() string { return self.rpcMethod } -func (self *CmdExecuteAction) RpcParams(ptr, reset bool) interface{} { +func (self *CmdExecuteAction) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrExecuteAction{Direction: utils.OUT} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdExecuteAction) PostprocessRpcParams() error { diff --git a/console/active_sessions.go b/console/active_sessions.go index 87d4a941a..db3c16a3f 100644 --- a/console/active_sessions.go +++ b/console/active_sessions.go @@ -48,14 +48,11 @@ func (self *CmdActiveSessions) RpcMethod() string { return self.rpcMethod } -func (self *CmdActiveSessions) RpcParams(ptr, reset bool) interface{} { +func (self *CmdActiveSessions) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrGetSMASessions{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdActiveSessions) PostprocessRpcParams() error { diff --git a/console/balance_debit.go b/console/balance_debit.go index 1b1b5d79c..ab6f45ec8 100644 --- a/console/balance_debit.go +++ b/console/balance_debit.go @@ -48,14 +48,11 @@ func (self *CmdDebitBalance) RpcMethod() string { return self.rpcMethod } -func (self *CmdDebitBalance) RpcParams(ptr, reset bool) interface{} { +func (self *CmdDebitBalance) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.CallDescriptor{Direction: "*out"} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdDebitBalance) PostprocessRpcParams() error { diff --git a/console/balance_set.go b/console/balance_set.go index d012fb05a..89f6a70c5 100644 --- a/console/balance_set.go +++ b/console/balance_set.go @@ -48,14 +48,11 @@ func (self *CmdAddBalance) RpcMethod() string { return self.rpcMethod } -func (self *CmdAddBalance) RpcParams(ptr, reset bool) interface{} { +func (self *CmdAddBalance) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &v1.AttrAddBalance{BalanceType: utils.MONETARY, Overwrite: false} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdAddBalance) PostprocessRpcParams() error { diff --git a/console/cache_age.go b/console/cache_age.go index 3e0177e37..e1bc27bf2 100644 --- a/console/cache_age.go +++ b/console/cache_age.go @@ -45,14 +45,11 @@ func (self *CmdGetCacheAge) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetCacheAge) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetCacheAge) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetCacheAge) PostprocessRpcParams() error { diff --git a/console/cache_reload.go b/console/cache_reload.go index 555ffc86a..14547be0f 100644 --- a/console/cache_reload.go +++ b/console/cache_reload.go @@ -46,14 +46,11 @@ func (self *CmdReloadCache) RpcMethod() string { return self.rpcMethod } -func (self *CmdReloadCache) RpcParams(ptr, reset bool) interface{} { +func (self *CmdReloadCache) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.ApiReloadCache{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdReloadCache) PostprocessRpcParams() error { diff --git a/console/cache_stats.go b/console/cache_stats.go index f68d52a59..eef3be100 100644 --- a/console/cache_stats.go +++ b/console/cache_stats.go @@ -45,14 +45,11 @@ func (self *CmdGetCacheStats) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetCacheStats) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetCacheStats) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrCacheStats{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetCacheStats) PostprocessRpcParams() error { diff --git a/console/callcost.go b/console/callcost.go index 6093dc19a..694c770ca 100644 --- a/console/callcost.go +++ b/console/callcost.go @@ -49,14 +49,11 @@ func (self *CmdGetCostDetails) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetCostDetails) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetCostDetails) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrGetCallCost{RunId: utils.DEFAULT_RUNID} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetCostDetails) PostprocessRpcParams() error { diff --git a/console/cdrs_export.go b/console/cdrs_export.go index 7defe1451..194345f14 100644 --- a/console/cdrs_export.go +++ b/console/cdrs_export.go @@ -45,14 +45,11 @@ func (self *CmdExportCdrs) RpcMethod() string { return self.rpcMethod } -func (self *CmdExportCdrs) RpcParams(ptr, reset bool) interface{} { +func (self *CmdExportCdrs) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrExportCdrsToFile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdExportCdrs) PostprocessRpcParams() error { diff --git a/console/cdrs_rem.go b/console/cdrs_rem.go index 5b3c097c4..628f2226c 100644 --- a/console/cdrs_rem.go +++ b/console/cdrs_rem.go @@ -45,14 +45,11 @@ func (self *CmdRemCdrs) RpcMethod() string { return self.rpcMethod } -func (self *CmdRemCdrs) RpcParams(ptr, reset bool) interface{} { +func (self *CmdRemCdrs) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrRemCdrs{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdRemCdrs) PostprocessRpcParams() error { diff --git a/console/cdrstats_metrics.go b/console/cdrstats_metrics.go index 9ae874cd9..4f94e25b8 100644 --- a/console/cdrstats_metrics.go +++ b/console/cdrstats_metrics.go @@ -45,14 +45,11 @@ func (self *CmdCdrStatsMetrics) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrStatsMetrics) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrStatsMetrics) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &v1.AttrGetMetrics{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrStatsMetrics) PostprocessRpcParams() error { diff --git a/console/cdrstats_queue.go b/console/cdrstats_queue.go index b58c4f7a9..f7db33737 100644 --- a/console/cdrstats_queue.go +++ b/console/cdrstats_queue.go @@ -44,14 +44,11 @@ func (self *CmdCdrStatsQueue) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrStatsQueue) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrStatsQueue) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrStatsQueue) PostprocessRpcParams() error { diff --git a/console/cdrstats_queue_triggers.go b/console/cdrstats_queue_triggers.go index 0218515a0..d9f5d3dfb 100644 --- a/console/cdrstats_queue_triggers.go +++ b/console/cdrstats_queue_triggers.go @@ -44,14 +44,11 @@ func (self *CmdCdrStatsQueueTriggers) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrStatsQueueTriggers) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrStatsQueueTriggers) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrStatsQueueTriggers) PostprocessRpcParams() error { diff --git a/console/cdrstats_queueids.go b/console/cdrstats_queueids.go index 288534c54..4427b0631 100644 --- a/console/cdrstats_queueids.go +++ b/console/cdrstats_queueids.go @@ -42,14 +42,11 @@ func (self *CmdCdrStatsQueueIds) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrStatsQueueIds) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrStatsQueueIds) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrStatsQueueIds) PostprocessRpcParams() error { diff --git a/console/cdrstats_reload.go b/console/cdrstats_reload.go index 29143a2ce..01c59923c 100644 --- a/console/cdrstats_reload.go +++ b/console/cdrstats_reload.go @@ -47,14 +47,11 @@ func (self *CmdCdrReloadQueues) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrReloadQueues) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrReloadQueues) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrCDRStatsReloadQueues{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrReloadQueues) PostprocessRpcParams() error { diff --git a/console/cdrstats_reset.go b/console/cdrstats_reset.go index d2f942ae1..bb847b34b 100644 --- a/console/cdrstats_reset.go +++ b/console/cdrstats_reset.go @@ -45,14 +45,11 @@ func (self *CmdCdrResetQueues) RpcMethod() string { return self.rpcMethod } -func (self *CmdCdrResetQueues) RpcParams(ptr, reset bool) interface{} { +func (self *CmdCdrResetQueues) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrCDRStatsReloadQueues{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdCdrResetQueues) PostprocessRpcParams() error { diff --git a/console/command.go b/console/command.go index d7d192ba2..feb801808 100644 --- a/console/command.go +++ b/console/command.go @@ -33,7 +33,7 @@ type Commander interface { FromArgs(args string, verbose bool) error // Load data from os arguments or flag.Args() Usage() string // usage message RpcMethod() string // Method which should be called remotely - RpcParams(bool, bool) interface{} // Parameters to send out on rpc + RpcParams(bool) interface{} // Parameters to send out on rpc PostprocessRpcParams() error // Corrects rpc parameters when needed RpcResult() interface{} // Only requirement is to have a String method to print on console ClientArgs() []string // for autocompletion @@ -88,3 +88,5 @@ type StringWrapper struct { type StringSliceWrapper struct { Items []string } + +type EmptyWrapper struct{} diff --git a/console/command_executer.go b/console/command_executer.go index 4d7e2595d..97620f3bb 100644 --- a/console/command_executer.go +++ b/console/command_executer.go @@ -40,13 +40,13 @@ type CommandExecuter struct { } func (ce *CommandExecuter) Usage() string { - jsn, _ := json.Marshal(ce.command.RpcParams(true, true)) + jsn, _ := json.Marshal(ce.command.RpcParams(true)) return fmt.Sprintf("\n\tUsage: %s %s \n", ce.command.Name(), FromJSON(jsn, ce.command.ClientArgs())) } // Parses command line args and builds CmdBalance value func (ce *CommandExecuter) FromArgs(args string, verbose bool) error { - params := ce.command.RpcParams(true, true) + params := ce.command.RpcParams(true) if err := json.Unmarshal(ToJSON(args), params); err != nil { return err } @@ -59,6 +59,10 @@ func (ce *CommandExecuter) FromArgs(args string, verbose bool) error { func (ce *CommandExecuter) clientArgs(iface interface{}) (args []string) { val := reflect.ValueOf(iface) + if val.Kind() == reflect.Ptr { + val = val.Elem() + iface = val.Interface() + } typ := reflect.TypeOf(iface) for i := 0; i < typ.NumField(); i++ { valField := val.Field(i) @@ -74,7 +78,7 @@ func (ce *CommandExecuter) clientArgs(iface interface{}) (args []string) { } func (ce *CommandExecuter) ClientArgs() (args []string) { - return ce.clientArgs(ce.command.RpcParams(false, true)) + return ce.clientArgs(ce.command.RpcParams(true)) } // To be overwritten by commands that do not need a rpc call diff --git a/console/cost.go b/console/cost.go index ab60d04bc..3e07a6e2e 100644 --- a/console/cost.go +++ b/console/cost.go @@ -47,14 +47,11 @@ func (self *CmdGetCost) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetCost) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetCost) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.CallDescriptor{Direction: "*out"} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetCost) PostprocessRpcParams() error { diff --git a/console/datacost.go b/console/datacost.go index 6df827e07..d9bf0a54a 100644 --- a/console/datacost.go +++ b/console/datacost.go @@ -51,14 +51,11 @@ func (self *CmdGetDataCost) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetDataCost) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetDataCost) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &v1.AttrGetDataCost{Direction: utils.OUT} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetDataCost) PostprocessRpcParams() error { diff --git a/console/destination.go b/console/destination.go index 9762081ba..1d80f1dee 100644 --- a/console/destination.go +++ b/console/destination.go @@ -45,14 +45,11 @@ func (self *CmdGetDestination) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetDestination) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetDestination) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetDestination) PostprocessRpcParams() error { diff --git a/console/destination_set.go b/console/destination_set.go index ed00b86b6..d6f045ebd 100644 --- a/console/destination_set.go +++ b/console/destination_set.go @@ -46,14 +46,11 @@ func (self *CmdSetDestination) RpcMethod() string { return self.rpcMethod } -func (self *CmdSetDestination) RpcParams(ptr, reset bool) interface{} { +func (self *CmdSetDestination) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrSetDestination{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdSetDestination) PostprocessRpcParams() error { diff --git a/console/lcr.go b/console/lcr.go index cbd2daeb4..711bcc9ef 100644 --- a/console/lcr.go +++ b/console/lcr.go @@ -48,14 +48,11 @@ func (self *CmdGetLcr) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetLcr) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetLcr) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.LcrRequest{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetLcr) PostprocessRpcParams() error { diff --git a/console/load_tp_from_folder.go b/console/load_tp_from_folder.go index 329e45318..c44220976 100644 --- a/console/load_tp_from_folder.go +++ b/console/load_tp_from_folder.go @@ -46,14 +46,11 @@ func (self *LoadTpFromFolder) RpcMethod() string { return self.rpcMethod } -func (self *LoadTpFromFolder) RpcParams(ptr, reset bool) interface{} { +func (self *LoadTpFromFolder) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.AttrLoadTpFromFolder{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *LoadTpFromFolder) PostprocessRpcParams() error { diff --git a/console/load_tp_from_stordb.go b/console/load_tp_from_stordb.go index 0d2af8714..5d2c7a998 100644 --- a/console/load_tp_from_stordb.go +++ b/console/load_tp_from_stordb.go @@ -46,14 +46,11 @@ func (self *LoadTpFromStorDb) RpcMethod() string { return self.rpcMethod } -func (self *LoadTpFromStorDb) RpcParams(ptr, reset bool) interface{} { +func (self *LoadTpFromStorDb) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &v1.AttrLoadTpFromStorDb{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *LoadTpFromStorDb) PostprocessRpcParams() error { diff --git a/console/maxduration.go b/console/maxduration.go index 2e04868de..b20d5f8e0 100644 --- a/console/maxduration.go +++ b/console/maxduration.go @@ -47,14 +47,11 @@ func (self *CmdGetMaxDuration) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetMaxDuration) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetMaxDuration) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.CallDescriptor{Direction: "*out"} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetMaxDuration) PostprocessRpcParams() error { diff --git a/console/parse.go b/console/parse.go index 558d024b4..f7c5ede56 100644 --- a/console/parse.go +++ b/console/parse.go @@ -49,14 +49,11 @@ func (self *CmdParse) RpcMethod() string { return "" } -func (self *CmdParse) RpcParams(ptr, reset bool) interface{} { +func (self *CmdParse) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &AttrParse{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdParse) RpcResult() interface{} { diff --git a/console/publish.go b/console/publish.go index 41797a178..c46c68a82 100644 --- a/console/publish.go +++ b/console/publish.go @@ -44,14 +44,11 @@ func (self *CmdPublish) RpcMethod() string { return self.rpcMethod } -func (self *CmdPublish) RpcParams(ptr, reset bool) interface{} { +func (self *CmdPublish) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.PublishInfo{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdPublish) PostprocessRpcParams() error { diff --git a/console/ratingprofile_set.go b/console/ratingprofile_set.go index 19c1597b8..0989bea58 100644 --- a/console/ratingprofile_set.go +++ b/console/ratingprofile_set.go @@ -46,14 +46,11 @@ func (self *CmdSetRatingProfile) RpcMethod() string { return self.rpcMethod } -func (self *CmdSetRatingProfile) RpcParams(ptr, reset bool) interface{} { +func (self *CmdSetRatingProfile) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &utils.TPRatingProfile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdSetRatingProfile) PostprocessRpcParams() error { diff --git a/console/scheduler_reload.go b/console/scheduler_reload.go index b9fa8a11e..a5a1c687c 100644 --- a/console/scheduler_reload.go +++ b/console/scheduler_reload.go @@ -43,14 +43,11 @@ func (self *CmdReloadScheduler) RpcMethod() string { return self.rpcMethod } -func (self *CmdReloadScheduler) RpcParams(ptr, reset bool) interface{} { +func (self *CmdReloadScheduler) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdReloadScheduler) PostprocessRpcParams() error { diff --git a/console/sharedgroup.go b/console/sharedgroup.go index 5ed688fc0..32b64fc22 100644 --- a/console/sharedgroup.go +++ b/console/sharedgroup.go @@ -45,14 +45,11 @@ func (self *CmdGetSharedGroup) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetSharedGroup) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetSharedGroup) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetSharedGroup) PostprocessRpcParams() error { diff --git a/console/status.go b/console/status.go index efa15a8ce..191aa1966 100644 --- a/console/status.go +++ b/console/status.go @@ -30,7 +30,7 @@ func init() { type CmdStatus struct { name string rpcMethod string - rpcParams *StringWrapper + rpcParams *EmptyWrapper *CommandExecuter } @@ -42,14 +42,11 @@ func (self *CmdStatus) RpcMethod() string { return self.rpcMethod } -func (self *CmdStatus) RpcParams(ptr, reset bool) interface{} { +func (self *CmdStatus) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { - self.rpcParams = &StringWrapper{} + self.rpcParams = &EmptyWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdStatus) PostprocessRpcParams() error { diff --git a/console/subscribe.go b/console/subscribe.go index 25c8f3e42..cb71edabc 100644 --- a/console/subscribe.go +++ b/console/subscribe.go @@ -44,14 +44,11 @@ func (self *CmdSubscribe) RpcMethod() string { return self.rpcMethod } -func (self *CmdSubscribe) RpcParams(ptr, reset bool) interface{} { +func (self *CmdSubscribe) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.SubscribeInfo{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdSubscribe) PostprocessRpcParams() error { diff --git a/console/subscribers.go b/console/subscribers.go index 4a37d0496..505ec1c77 100644 --- a/console/subscribers.go +++ b/console/subscribers.go @@ -44,14 +44,11 @@ func (self *CmdShowSubscribers) RpcMethod() string { return self.rpcMethod } -func (self *CmdShowSubscribers) RpcParams(ptr, reset bool) interface{} { +func (self *CmdShowSubscribers) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdShowSubscribers) PostprocessRpcParams() error { diff --git a/console/triggeredaction_add.go b/console/triggeredaction_add.go index 122c40901..298782b6c 100644 --- a/console/triggeredaction_add.go +++ b/console/triggeredaction_add.go @@ -45,14 +45,11 @@ func (self *CmdAddTriggeredAction) RpcMethod() string { return self.rpcMethod } -func (self *CmdAddTriggeredAction) RpcParams(ptr, reset bool) interface{} { +func (self *CmdAddTriggeredAction) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &v1.AttrAddActionTrigger{BalanceDirection: "*out"} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdAddTriggeredAction) PostprocessRpcParams() error { diff --git a/console/unsubscribe.go b/console/unsubscribe.go index 806922388..0ebc534ea 100644 --- a/console/unsubscribe.go +++ b/console/unsubscribe.go @@ -44,14 +44,11 @@ func (self *CmdUnsubscribe) RpcMethod() string { return self.rpcMethod } -func (self *CmdUnsubscribe) RpcParams(ptr, reset bool) interface{} { +func (self *CmdUnsubscribe) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.SubscribeInfo{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdUnsubscribe) PostprocessRpcParams() error { diff --git a/console/user_addindex.go b/console/user_addindex.go index d0408340a..c0b660e93 100644 --- a/console/user_addindex.go +++ b/console/user_addindex.go @@ -43,14 +43,11 @@ func (self *CmdUserAddIndex) RpcMethod() string { return self.rpcMethod } -func (self *CmdUserAddIndex) RpcParams(ptr, reset bool) interface{} { +func (self *CmdUserAddIndex) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &StringSliceWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdUserAddIndex) PostprocessRpcParams() error { diff --git a/console/user_indexes.go b/console/user_indexes.go index 547e67381..6a713044a 100644 --- a/console/user_indexes.go +++ b/console/user_indexes.go @@ -31,7 +31,7 @@ func init() { type CmdUserShowIndexes struct { name string rpcMethod string - rpcParams *StringWrapper + rpcParams *EmptyWrapper *CommandExecuter } @@ -43,14 +43,11 @@ func (self *CmdUserShowIndexes) RpcMethod() string { return self.rpcMethod } -func (self *CmdUserShowIndexes) RpcParams(ptr, reset bool) interface{} { +func (self *CmdUserShowIndexes) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { - self.rpcParams = &StringWrapper{} + self.rpcParams = &EmptyWrapper{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdUserShowIndexes) PostprocessRpcParams() error { diff --git a/console/user_remove.go b/console/user_remove.go index 8e8658e81..f0a0a3aec 100644 --- a/console/user_remove.go +++ b/console/user_remove.go @@ -45,14 +45,11 @@ func (self *CmdUserRemove) RpcMethod() string { return self.rpcMethod } -func (self *CmdUserRemove) RpcParams(ptr, reset bool) interface{} { +func (self *CmdUserRemove) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.UserProfile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdUserRemove) PostprocessRpcParams() error { diff --git a/console/user_set.go b/console/user_set.go index e531fe8e3..39cd8239f 100644 --- a/console/user_set.go +++ b/console/user_set.go @@ -45,14 +45,11 @@ func (self *CmdSetUser) RpcMethod() string { return self.rpcMethod } -func (self *CmdSetUser) RpcParams(ptr, reset bool) interface{} { +func (self *CmdSetUser) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.UserProfile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdSetUser) PostprocessRpcParams() error { diff --git a/console/user_update.go b/console/user_update.go index 908b54376..ef80a4f27 100644 --- a/console/user_update.go +++ b/console/user_update.go @@ -45,14 +45,11 @@ func (self *CmdUpdateUser) RpcMethod() string { return self.rpcMethod } -func (self *CmdUpdateUser) RpcParams(ptr, reset bool) interface{} { +func (self *CmdUpdateUser) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.UserProfile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdUpdateUser) PostprocessRpcParams() error { diff --git a/console/users.go b/console/users.go index 89492d7f0..e343297cd 100644 --- a/console/users.go +++ b/console/users.go @@ -46,14 +46,11 @@ func (self *CmdGetUsers) RpcMethod() string { return self.rpcMethod } -func (self *CmdGetUsers) RpcParams(ptr, reset bool) interface{} { +func (self *CmdGetUsers) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { self.rpcParams = &engine.UserProfile{} } - if ptr { - return self.rpcParams - } - return *self.rpcParams + return self.rpcParams } func (self *CmdGetUsers) PostprocessRpcParams() error { @@ -61,6 +58,6 @@ func (self *CmdGetUsers) PostprocessRpcParams() error { } func (self *CmdGetUsers) RpcResult() interface{} { - s := []*engine.UserProfile{} + s := engine.UserProfiles{} return &s } diff --git a/data/tariffplans/tutorial/User.csv b/data/tariffplans/tutorial/Users.csv similarity index 100% rename from data/tariffplans/tutorial/User.csv rename to data/tariffplans/tutorial/Users.csv diff --git a/engine/calldesc.go b/engine/calldesc.go index 45d3c4289..417f3c0f6 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -68,7 +68,7 @@ var ( globalRoundingDecimals = 10 historyScribe history.Scribe pubSubServer PublisherSubscriber - //historyScribe, _ = history.NewMockScribe() + userService UserService ) // Exported method to set the storage getter. @@ -108,6 +108,10 @@ func SetPubSub(ps PublisherSubscriber) { pubSubServer = ps } +func SetUserService(us UserService) { + userService = us +} + func Publish(event CgrEvent) { if pubSubServer != nil { var s string diff --git a/engine/users.go b/engine/users.go index 95f7a2d9d..ce1cfc8a2 100644 --- a/engine/users.go +++ b/engine/users.go @@ -1,6 +1,7 @@ package engine import ( + "sort" "strings" "github.com/cgrates/cgrates/utils" @@ -11,6 +12,25 @@ type UserProfile struct { Tenant string UserName string Profile map[string]string + ponder int +} + +type UserProfiles []*UserProfile + +func (ups UserProfiles) Len() int { + return len(ups) +} + +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) Sort() { + sort.Sort(ups) } func (ud *UserProfile) GetId() string { @@ -31,7 +51,7 @@ type UserService interface { SetUser(UserProfile, *string) error RemoveUser(UserProfile, *string) error UpdateUser(UserProfile, *string) error - GetUsers(UserProfile, *[]*UserProfile) error + GetUsers(UserProfile, *UserProfiles) error AddIndex([]string, *string) error GetIndexes(string, *map[string][]string) error } @@ -123,7 +143,7 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error { return nil } -func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { +func (um *UserMap) GetUsers(up UserProfile, results *UserProfiles) error { table := um.table // no index indexUnionKeys := make(map[string]bool) @@ -156,20 +176,34 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { } } - var candidates []*UserProfile + var candidates UserProfiles for key, values := range table { - if up.Tenant != "" && !strings.HasPrefix(key, up.Tenant+utils.CONCATENATED_KEY_SEP) { + ponder := 0 + tableUP := &UserProfile{ + Profile: values, + } + tableUP.SetId(key) + if up.Tenant != "" && tableUP.Tenant != "" && up.Tenant != tableUP.Tenant { continue } - if up.UserName != "" && !strings.HasSuffix(key, utils.CONCATENATED_KEY_SEP+up.UserName) { + if tableUP.Tenant != "" { + ponder += 1 + } + if up.UserName != "" && tableUP.UserName != "" && up.UserName != tableUP.UserName { continue } + if tableUP.UserName != "" { + ponder += 1 + } valid := true for k, v := range up.Profile { - if values[k] != v { + if tableUP.Profile[k] != "" && tableUP.Profile[k] != v { valid = false break } + if tableUP.Profile[k] != "" { + ponder += 1 + } } if !valid { continue @@ -177,11 +211,13 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { // all filters passed, add to candidates nup := &UserProfile{Profile: make(map[string]string)} nup.SetId(key) - for k, v := range values { + nup.ponder = ponder + for k, v := range tableUP.Profile { nup.Profile[k] = v } candidates = append(candidates, nup) } + candidates.Sort() *results = candidates return nil } @@ -307,7 +343,7 @@ func (ps *ProxyUserService) UpdateUser(ud UserProfile, reply *string) error { return ps.Client.Call("UsersV1.UpdateUser", ud, reply) } -func (ps *ProxyUserService) GetUsers(ud UserProfile, users *[]*UserProfile) error { +func (ps *ProxyUserService) GetUsers(ud UserProfile, users *UserProfiles) error { return ps.Client.Call("UsersV1.GetUsers", ud, users) } @@ -318,3 +354,50 @@ func (ps *ProxyUserService) AddIndex(indexes []string, reply *string) error { func (ps *ProxyUserService) GetIndexes(in string, reply *map[string][]string) error { return ps.Client.Call("UsersV1.AddIndex", in, reply) } + +func LoadUserProfile(in interface{}, extraFields string) (interface{}, error) { + m, err := utils.ToMapStringString(in) + if err != nil { + return nil, err + } + + up := &UserProfile{ + Profile: make(map[string]string), + } + tenant := m["Tenant"] + if tenant != "" && tenant != utils.USERS { + up.Tenant = tenant + } + delete(m, "Tenant") + + // clean empty and *user fields + for key, val := range m { + if val != "" && val != utils.USERS { + up.Profile[key] = val + } + } + + // add extra fields + if extraFields != "" { + extra, err := utils.GetMapExtraFields(in, extraFields) + if err != nil { + return nil, err + } + for key, val := range extra { + if val != "" { + up.Profile[key] = val + } + } + } + ups := UserProfiles{} + if err := userService.GetUsers(*up, &ups); err != nil { + return nil, err + } + if len(ups) > 0 { + up = ups[0] + m := up.Profile + m["Tenant"] = up.Tenant + return utils.FromMapStringString(m, in) + } + return nil, utils.ErrNotFound +} diff --git a/engine/users_test.go b/engine/users_test.go index ad1dfec9d..12b14c21f 100644 --- a/engine/users_test.go +++ b/engine/users_test.go @@ -1,6 +1,7 @@ package engine import ( + "reflect" "testing" "github.com/cgrates/cgrates/utils" @@ -148,9 +149,9 @@ func TestUsersGetFull(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 1 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -163,9 +164,9 @@ func TestUsersGetTenant(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 1 { t.Error("error getting users: ", results) } } @@ -178,9 +179,9 @@ func TestUsersGetUserName(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 1 { t.Error("error getting users: ", results) } } @@ -193,9 +194,9 @@ func TestUsersGetNotFoundProfile(t *testing.T) { "o": "p", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -207,9 +208,9 @@ func TestUsersGetMissingTenant(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 2 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -221,9 +222,9 @@ func TestUsersGetMissingUserName(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 2 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -234,7 +235,7 @@ func TestUsersGetMissingId(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) if len(results) != 4 { t.Error("error getting users: ", results) @@ -248,13 +249,30 @@ func TestUsersGetMissingIdTwo(t *testing.T) { "x": "y", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 1 { + if len(results) != 4 { t.Error("error getting users: ", results) } } +func TestUsersGetMissingIdTwoSort(t *testing.T) { + up := UserProfile{ + Profile: map[string]string{ + "t": "v", + "x": "y", + }, + } + results := UserProfiles{} + testMap.GetUsers(up, &results) + if len(results) != 4 { + t.Error("error getting users: ", results) + } + if results[0].GetId() != "test1:user1" { + t.Errorf("Error sorting profiles: %+v", results[0]) + } +} + func TestUsersAddIndex(t *testing.T) { var r string testMap.AddIndex([]string{"t"}, &r) @@ -297,9 +315,9 @@ func TestUsersGetFullindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 1 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -315,9 +333,9 @@ func TestUsersGetTenantindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 1 { t.Error("error getting users: ", results) } } @@ -333,9 +351,9 @@ func TestUsersGetUserNameindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 1 { t.Error("error getting users: ", results) } } @@ -351,9 +369,9 @@ func TestUsersGetNotFoundProfileindex(t *testing.T) { "o": "p", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 0 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -368,9 +386,9 @@ func TestUsersGetMissingTenantindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 2 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -385,9 +403,9 @@ func TestUsersGetMissingUserNameindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 2 { + if len(results) != 3 { t.Error("error getting users: ", results) } } @@ -401,7 +419,7 @@ func TestUsersGetMissingIdindex(t *testing.T) { "t": "v", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) if len(results) != 4 { t.Error("error getting users: ", results) @@ -418,9 +436,9 @@ func TestUsersGetMissingIdTwoINdex(t *testing.T) { "x": "y", }, } - results := make([]*UserProfile, 0) + results := UserProfiles{} testMap.GetUsers(up, &results) - if len(results) != 1 { + if len(results) != 4 { t.Error("error getting users: ", results) } } @@ -501,3 +519,136 @@ func TestUsersAddUpdateRemoveIndexes(t *testing.T) { t.Error("error adding indexes: ", tm.index) } } + +func TestUsersStoredCDRGetLoadUserProfile(t *testing.T) { + userService = &UserMap{ + table: map[string]map[string]string{ + "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"}, + ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"}, + "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"}, + "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13"}, + }, + index: make(map[string]map[string]bool), + } + + ur := &UsageRecord{ + TOR: utils.USERS, + ReqType: utils.USERS, + Direction: "*out", + Tenant: "", + Category: "call", + Account: utils.USERS, + Subject: utils.USERS, + Destination: utils.USERS, + SetupTime: utils.USERS, + AnswerTime: utils.USERS, + Usage: "13", + } + + out, err := LoadUserProfile(ur, "") + if err != nil { + t.Error("Error loading user profile: ", err) + } + expected := &UsageRecord{ + TOR: "04", + ReqType: "4", + Direction: "*out", + Tenant: "", + Category: "call", + Account: "rif", + Subject: "0726", + Destination: "+404", + SetupTime: "s4", + AnswerTime: "t4", + Usage: "13", + } + *ur = out.(UsageRecord) + if !reflect.DeepEqual(ur, expected) { + t.Errorf("Expected: %+v got: %+v", expected, ur) + } +} + +func TestUsersStoredCDRGetLoadUserProfileExtraFields(t *testing.T) { + userService = &UserMap{ + table: map[string]map[string]string{ + "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"}, + ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"}, + "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"}, + "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "1"}, + }, + index: make(map[string]map[string]bool), + } + + ur := &ExternalCdr{ + TOR: utils.USERS, + ReqType: utils.USERS, + Direction: "*out", + Tenant: "", + Category: "call", + Account: utils.USERS, + Subject: utils.USERS, + Destination: utils.USERS, + SetupTime: utils.USERS, + AnswerTime: utils.USERS, + Usage: "13", + ExtraFields: map[string]string{ + "Test": "1", + }, + } + + out, err := LoadUserProfile(ur, "ExtraFields") + if err != nil { + t.Error("Error loading user profile: ", err) + } + expected := &ExternalCdr{ + TOR: "04", + ReqType: "4", + Direction: "*out", + Tenant: "", + Category: "call", + Account: "rif", + Subject: "0726", + Destination: "+404", + SetupTime: "s4", + AnswerTime: "t4", + Usage: "13", + } + *ur = out.(ExternalCdr) + if !reflect.DeepEqual(ur, expected) { + t.Errorf("Expected: %+v got: %+v", expected, ur) + } +} + +func TestUsersStoredCDRGetLoadUserProfileExtraFieldsNotFound(t *testing.T) { + userService = &UserMap{ + table: map[string]map[string]string{ + "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"}, + ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"}, + "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"}, + "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "2"}, + }, + index: make(map[string]map[string]bool), + } + + ur := &ExternalCdr{ + TOR: utils.USERS, + ReqType: utils.USERS, + Direction: "*out", + Tenant: "", + Category: "call", + Account: utils.USERS, + Subject: utils.USERS, + Destination: utils.USERS, + SetupTime: utils.USERS, + AnswerTime: utils.USERS, + Usage: "13", + ExtraFields: map[string]string{ + "Test": "1", + }, + } + + _, err := LoadUserProfile(ur, "ExtraFields") + if err != utils.ErrNotFound { + t.Error("Error detecting err in loading user profile: ", err) + } +} diff --git a/utils/consts.go b/utils/consts.go index 1c69ac9b1..7300cfcc1 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -83,6 +83,7 @@ const ( ROUNDING_DOWN = "*down" ANY = "*any" ASAP = "*asap" + USERS = "*users" COMMENT_CHAR = '#' CSV_SEP = ',' FALLBACK_SEP = ';' diff --git a/utils/struct.go b/utils/struct.go index 46edb4e93..5904341be 100644 --- a/utils/struct.go +++ b/utils/struct.go @@ -61,7 +61,7 @@ func NonemptyStructFields(s interface{}) map[string]interface{} { } // Converts a struct to map -func StrucToMap(s interface{}) map[string]interface{} { +/*func StrucToMap(s interface{}) map[string]interface{} { mp := make(map[string]interface{}) for i := 0; i < reflect.ValueOf(s).Elem().NumField(); i++ { fld := reflect.ValueOf(s).Elem().Field(i) @@ -75,6 +75,82 @@ func StrucToMap(s interface{}) map[string]interface{} { } } return mp +}*/ + +// Converts a struct to map[string]interface{} +func ToMapMapStringInterface(in interface{}) (map[string]interface{}, error) { + out := make(map[string]interface{}) + + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + typ := reflect.TypeOf(in) + for i := 0; i < v.NumField(); i++ { + out[typ.Field(i).Name] = v.Field(i).Interface() + } + return out, nil +} + +// Converts a struct to map[string]string +func ToMapStringString(in interface{}) (map[string]string, error) { + out := make(map[string]string) + + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + in = v.Interface() + } + typ := reflect.TypeOf(in) + for i := 0; i < v.NumField(); i++ { + // gets us a StructField + typField := typ.Field(i) + field := v.Field(i) + if field.Kind() == reflect.String { + out[typField.Name] = field.String() + } + } + return out, nil +} + +// Converts a struct to map[string]string +func GetMapExtraFields(in interface{}, extraFields string) (map[string]string, error) { + out := make(map[string]string) + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + in = v.Interface() + } + field := v.FieldByName(extraFields) + if field.Kind() == reflect.Map { + keys := field.MapKeys() + for _, key := range keys { + out[key.String()] = field.MapIndex(key).String() + } + } + return out, nil +} + +func FromMapStringString(m map[string]string, in interface{}) (interface{}, error) { + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + in = v.Interface() + } + st := reflect.TypeOf(in) + elem := reflect.New(st).Elem() + for fieldName, fieldValue := range m { + field := elem.FieldByName(fieldName) + if field.IsValid() { + + if field.Kind() == reflect.String { + if v.FieldByName(fieldName).String() != "" { + field.SetString(fieldValue) + } + } + } + } + return elem.Interface(), nil } // Update struct with map fields, returns not matching map keys, s is a struct to be updated diff --git a/utils/struct_test.go b/utils/struct_test.go new file mode 100644 index 000000000..12723952f --- /dev/null +++ b/utils/struct_test.go @@ -0,0 +1,89 @@ +package utils + +import ( + "reflect" + "testing" +) + +func TestStructMapStruct(t *testing.T) { + type TestStruct struct { + Name string + Surname string + Address string + Other string + } + ts := &TestStruct{ + Name: "1", + Surname: "2", + Address: "3", + Other: "", + } + m, err := ToMapStringString(ts) + if err != nil { + t.Error("Error converting to map: ", err) + } + out, err := FromMapStringString(m, ts) + if err != nil { + t.Error("Error converting to struct: ", err) + } + nts := out.(TestStruct) + if !reflect.DeepEqual(ts, &nts) { + t.Log(m) + t.Errorf("Expected: %+v got: %+v", ts, nts) + } +} + +func TestMapStructAddStructs(t *testing.T) { + type TestStruct struct { + Name string + Surname string + Address string + Other string + } + ts := &TestStruct{ + Name: "1", + Surname: "2", + Address: "3", + Other: "", + } + m, err := ToMapStringString(ts) + if err != nil { + t.Error("Error converting to map: ", err) + } + m["Test"] = "4" + out, err := FromMapStringString(m, ts) + if err != nil { + t.Error("Error converting to struct: ", err) + } + nts := out.(TestStruct) + if !reflect.DeepEqual(ts, &nts) { + t.Log(m) + t.Errorf("Expected: %+v got: %+v", ts, nts) + } +} + +func TestStructExtraFields(t *testing.T) { + ts := struct { + Name string + Surname string + Address string + ExtraFields map[string]string + }{ + Name: "1", + Surname: "2", + Address: "3", + ExtraFields: map[string]string{ + "k1": "v1", + "k2": "v2", + "k3": "v3", + }, + } + efMap, err := GetMapExtraFields(ts, "ExtraFields") + if err != nil { + t.Error("Error getting extra fields: ", err) + } + + if !reflect.DeepEqual(efMap, ts.ExtraFields) { + t.Errorf("expected: %v got: %v", ts.ExtraFields, efMap) + } +}