Skip to content

Instantly share code, notes, and snippets.

@mdellavo
Last active October 16, 2018 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdellavo/59e0a647d0025fc1c58219e98addc56d to your computer and use it in GitHub Desktop.
Save mdellavo/59e0a647d0025fc1c58219e98addc56d to your computer and use it in GitHub Desktop.

SafeString

A subclass of string that protects from unauthorized representation, returning a masked value.

class BasicChecker(object):
    def __init__(self, allowed):
        self.allowed = allowed

    def check_can_show(self):
        return self.allowed

class FixedMasker(object):
    def __init__(self, mask="*", mask_len=5):
        self.mask = mask
        self.mask_len = mask_len
        
    def mask(self, s):
        return self.mask * self.mask_len
        
class SafeString(str):
    def __new__(cls, s, checker, masker *args, **kwargs):
        obj = str.__new__(cls, s)
        obj.checker = checker
        obj.masker = masker
        return obj

    # Partial implementation - more methods would have to be overriden 
    def __str__(self):
        val = super(SafeString, self).__str__()
        return val if self.checker.check_can_show() else self.masker.mask(val)


if __name__ == "__main__":
    secret = "sekret"
    masker = FixedMasker()

    checker = BasicChecker(False)
    s = SafeString(secret, checker, masker)
    print(s)
    assert str(s) == "*****"

    checker = BasicChecker(True)
    s = SafeString(secret, checker, masker)
    print(s)
    assert str(s) == secret

Outstanding Issues

  • how do we hook into higher-level/business layers for checking, do we only use this in projections?
  • what other methods must be implemented to avoid leaking the string - slicing, etc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment