Eduard Lebedyuk · Jan 20, 2019 go to post

Try installing httpd from the package manager for your OS..

Add http to https redirect.

Maybe plugins go to https first, so redirect all traffic to https. Good for various cached links, etc.

Eduard Lebedyuk · Jan 18, 2019 go to post

If someone is interested, here's the same code but as a class:

/// Utility to match input against comma-separated string of masks.
Class util.Matcher
{

/// Returns $$$YES if input matches at least one element from the list
/// input - string to match
/// list - comma separated list of masks containig * and ?
/// write ##class(util.Matcher).MatchOr()
ClassMethod MatchOr(input As %String, list As %String) As %Boolean
{
    set ok = $$$NO
    for pie=1:1:$L(list,",") {
        set mask=$P(list,",",pie)
        if mask'="",..Match(input,mask) {
            set ok = $$$YES
        }
    }
    quit ok
}

/// Returns $$$YES if input matches all elements from the list
/// input - string to match
/// list - comma separated list of masks containig * and ?
/// write ##class(util.Matcher).MatchAnd()
ClassMethod MatchAnd(input As %String, list As %String) As %Boolean
{
    set ok = $$$YES
    for pie=1:1:$L(list,",") {
        set mask=$P(list,",",pie)
        if mask'="",'..Match(input,mask) {
            set ok = $$$NO
        }
    }
     quit ok
}

/// Returns $$$YES if input matches the mask
/// write ##class(util.Matcher).Match()
ClassMethod Match(input As %String, mask As %String) As %Boolean [ CodeMode = expression ]
{
input?@..MaskToPattern(mask)
}

/// Translate mask into a pattern
/// write ##class(util.Matcher).MaskToPattern()
ClassMethod MaskToPattern(mask As %String) As %String
{
    set pattern = ""
    set char = ""
    for pos = 1:1:$length(mask) {
        set curChar = $extract(mask, pos)
        if curChar = "*" {
            set pattern = pattern _ $select(char="":"", 1:"1"""_char_"""") _ ".E"
            set char = ""
        } elseif curChar = "?" {
            set pattern = pattern _ $select(char="":"", 1:"1"""_char_"""") _ "1E"
            set char = ""
        } else {
            set char = char _ curChar
        }
    }
    set pattern = pattern _ $select(char="":"", 1:"1"""_char_"""")
    quit pattern
}

}
Eduard Lebedyuk · Jan 18, 2019 go to post

You can store salt in the same table, it should just be unique (autogenerated) for each password.

There's a good explanation why that's enough, here.

Eduard Lebedyuk · Jan 16, 2019 go to post

Do not store passwords.

Store password hashes + Unique salt. When entered hash

Check $system.Encryption class for various hashing algorithms.

The only case where you need to store passwords is when they are used to authenticate Cache server against external systems.

In that case use the same $system.Encryption class to encrypt them for storage.

we're talking of 200-300+ passwords here.

Per user?

Eduard Lebedyuk · Jan 16, 2019 go to post

Is the "bi login" hosted on the same Cache server?

If so you'll need to add /dsw and /mdx2json to the same group/same cookie path as your app and you should be all set.

Eduard Lebedyuk · Jan 12, 2019 go to post

You could (and probably should) separate these parts of routines as separate methods or at least subroutines.

Eduard Lebedyuk · Jan 12, 2019 go to post

And if you don't have labels, adding them wouldn't break existing code.

For example you have this routine:

TEST
    write 1
    write 2
    write 3
    quit

It, when called would output

>do ^TEST
123

If you then add a label somewhere:

TEST
    write 1

MYLABEL
    write 2
    write 3
    quit

The routine would wok the same on previous calls:

>do ^TEST
123

But you'll also be able to call only the label:

>do MYLABEL^TEST
23
Eduard Lebedyuk · Jan 11, 2019 go to post

Can you ballpark the workload?

If it's not too big, I think the easiest solution would be just writing ObjectScript method that calculates what you need.

Eduard Lebedyuk · Jan 10, 2019 go to post

tFullValue should be always equal to tNumber regardless of tNumber value.

write $l(2.1)

>3
Eduard Lebedyuk · Jan 10, 2019 go to post

I'm curious about this

set tFullValue = $EXTRACT(tNumber,1,$length(tNumber))

in what cases tFullValue is not equal to tNumber?

Also after 2014 you can use * to denote last char like this:

set tFullValue = $EXTRACT(tNumber,1,*)
Eduard Lebedyuk · Jan 9, 2019 go to post

There's no default function to do it, but you can easily develop your own custom function. There's $IsValidNum ObjectScript function, which could be used to check that variable is a number. So something like this should work:

/// Functions to use in rule definitions.
Class Custom.Functions Extends Ens.Rule.FunctionSet
{

/// Returns 1 if a string is a number, 0 otherwise
ClassMethod IsValidNumber(string As %String) As %Boolean [ CodeMode = expression, Final ]
{
$ISVALIDNUM(string)
}

}
Eduard Lebedyuk · Jan 9, 2019 go to post

SendRequestAsync is available in all Ensemble Hosts (Services, Operations, Processes).

For Operations and Services the signature is:

Method SendRequestAsync(pTargetDispatchName As %String, pRequest As %Library.Persistent, pDescription As %String = "") As %Status

And for Processes the signature is:

Method SendRequestAsync(pTargetDispatchName As %String, pRequest As Request, pResponseRequired As %Boolean = 1, pCompletionKey As %String = "", pDescription As %String = "") As %Status
Eduard Lebedyuk · Jan 9, 2019 go to post

All possible job states (from EnsConstrains.inc):

  • $$$eJobStatusStarting
  • $$$eJobStatusRegistered
  • $$$eJobStatusVisiting
  • $$$eJobStatusRunning
  • $$$eJobStatusDeQueuing
  • $$$eJobStatusQuiescent
  • $$$eJobStatusError
  • $$$eJobStatusHalted
  • $$$eJobStatusTerminated
Eduard Lebedyuk · Jan 8, 2019 go to post

In the future please don't combine separate questions into one post.

I am looking for a way to detimerine if a certain namespace is ensemble enabled.

To check that some <namespace> has Ensemble enabled call:

write ##class(%EnsembleMgr).IsEnsembleNamespace(<namespace>)

where <namespace> defaults to current namespace.

Log some information to the console log file with a certain error level.

%SYS.System class provides the WriteToConsoleLog method, which you can use to write to the cconsole.log file.

Eduard Lebedyuk · Jan 5, 2019 go to post

Use %Stream.GlobalBinary to pass streams without saving them on disk. Also use Ens.StreamContainer as an interoperability message class.

If you used %Stream.TmpBinary class to hold your stream, it would not be saved.

Eduard Lebedyuk · Jan 4, 2019 go to post

If you have SSL config named, say, "AWS" try to set SMTP SSLConfiguration setting to "AWS*" (with asterisk on end). It can help.

Eduard Lebedyuk · Jan 4, 2019 go to post

Click "Visual Trace" link to view details.

In your case there's 403 error, so you're not authenticated.

Check this topic for AWS authorization options.

Eduard Lebedyuk · Jan 4, 2019 go to post

- If I have a global available in a certain namespace, can I use InterSystems SQL to query those globals?  

- How do existing globals and creating classes work?  Like I have a Person global right now.  Can I turn that into a class and manipulate the data that way?

You'll need class mapping to query globals via SQL. Check article series  The Art of Mapping Globals to Classes by @Brendan.Bannon.

- I'm used to Java where you can write a class and then write a driver class to test your classes and methods. Or simply just test your newly created classes and methods in the main method (wherever that lies in your code).  Is there something similar in Studio?  I can write classes but then they are compiled and I have to go to the terminal and test them?  Is this where routines come into play in Studio?

You can configure Studio or Atelier debugger to run any class method. There's no need to use routines for that.

Eduard Lebedyuk · Dec 27, 2018 go to post

The input pattern is not constant, it's just an example.

I'd rather avoid parsing my input pattern and translating it into Cache pattern.