Beispiel #1
0
    def process_value(self, value, property, prefix=""):
        unique = property.get('unique', True)
        expected_type = property.expected_type.key
        
        at = {"key": self.key, "property": prefix + property.name}

        if isinstance(value, list):
            if unique is True:
                raise common.BadData(message='expected atom, found list', at=at, value=value)
            
            p = web.storage(property.copy())
            p.unique = True
            return [self.process_value(v, p) for v in value]
    
        if unique is False:    
            raise common.BadData(message='expected list, found atom', at=at, value=value)

        type_found = common.find_type(value)
    
        if expected_type in common.primitive_types:
            # string can be converted to any type and int can be converted to float
            try:
                if type_found == '/type/string' and expected_type != '/type/string':
                    value = common.primitive_types[expected_type](value)
                elif type_found == '/type/int' and expected_type == '/type/float':
                    value = float(value)
            except ValueError, e:
                raise common.BadData(message=str(e), at=at, value=value)
Beispiel #2
0
    def get_user_email(self, username):
        logger.debug("get_user_email", username)

        if username.startswith("/"):
            # this is user key
            userkey = username
            username = username.split("/")[-1]
        else:
            userkey = get_user_root() + username

        details = self.site.store.get_user_details(username)

        logger.debug("get_user_email details %s %s", username, details)

        if details:
            return details.email

        doc = self.site.store.store.get("account/" + username)
        logger.debug("get_user_email doc %s", doc)

        if doc and doc.get("type") == "pending-account":
            return doc['email']

        raise common.BadData(message='No user registered with username: ' +
                             username,
                             error="account_not_found")
Beispiel #3
0
    def check_reset_code(self, username, code):
        SEC_PER_WEEK = 7 * 24 * 3600
        timestamp, code = code.split('$', 1)

        # code is valid only for a week
        if int(timestamp) + SEC_PER_WEEK < int(time.time()):
            raise common.BadData(message='Password Reset code expired')

        username = get_user_root() + username
        details = self.site.store.get_user_details(username)

        if not details:
            raise common.BadData(message="Invalid username")

        text = details.password + '$' + timestamp

        if not self._check_salted_hash(self.secret_key, text, code):
            raise common.BadData(message="Invaid password reset code")
Beispiel #4
0
    def register1(self, username, email, enc_password, data, ip=None, timestamp=None):
        ip = ip or web.ctx.ip
        key = get_user_root() + username
        if self.site.get(key):
            raise common.BadData(message="User already exists: " + username)

        if self.site.store.find_user(email):
            raise common.BadData(message='Email is already used: ' + email)

        def f():
            web.ctx.disable_permission_check = True

            d = web.storage({"key": key, "type": {"key": "/type/user"}})
            d.update(data)
            self.site.save(key, d, timestamp=timestamp, author=d, comment="Created new account")

            q = make_query(d)
            account_bot = config.get('account_bot')
            account_bot = account_bot and web.storage({"key": account_bot, "type": {"key": "/type/user"}})
            self.site.save_many(q, ip=ip, timestamp=timestamp, author=account_bot, action='register', comment="Setup new account")
            self.site.store.register(key, email, enc_password)
            self.update_user_details(username, verified=True, active=True)

            # Add account doc to store
            olddoc = self.site.store.store.get("account/" + username) or {}
            
            doc = {
                "_key": "account/" + username,
                "_rev": olddoc.get("_rev"),
                "type": "account",
                "registered_on": olddoc['registered_on'],
                "activated_on": timestamp.isoformat(),
                "last_login": timestamp.isoformat(),
            }
            self.site.store.store.put("account/" + username, doc)

        timestamp = timestamp or datetime.datetime.utcnow()
        self.site.store.transact(f)

        event_data = dict(data, username=username, email=email, password=enc_password)
        self.site._fire_event("register", timestamp=timestamp, ip=ip or web.ctx.ip, username=None, data=event_data)

        self.set_auth_token(key)
        return username
Beispiel #5
0
    def POST_activate(self, site):
        i = input('username')

        a = site.get_account_manager()
        status = a.activate(i.username)
        if status == "ok":
            return {"ok": "true"}
        else:
            raise common.BadData(error_code=status,
                                 message="Account activation failed.")
Beispiel #6
0
    def POST_login(self, site):
        i = input('username', 'password')
        a = site.get_account_manager()
        status = a.login(i.username, i.password)

        if status == "ok":
            a.set_auth_token(get_user_root() + i.username)
            return {"ok": True}
        else:
            raise common.BadData(code=status, message="Login failed")
Beispiel #7
0
def input(*required, **defaults):
    if 'infobase_input' in web.ctx:
        d = web.ctx.infobase_input
    else:
        d = web.input()

    for k in required:
        if k not in d:
            raise common.BadData(message="Missing argument: " + repr(k))

    result = web.storage(defaults)
    result.update(d)
    return result
Beispiel #8
0
    def update_user(self, old_password, new_password, email):
        user = self.get_user()
        if user is None:
            raise common.PermissionDenied(message="Not logged in")

        if not self.checkpassword(user.key, old_password):
            raise common.BadData(message='Invalid Password')
        
        new_password and self.assert_password(new_password)
        email and self.assert_email(email)
        
        enc_password = new_password and self._generate_salted_hash(self.secret_key, new_password)
        self.update_user1(user, enc_password, email)
Beispiel #9
0
    def store_account_info(self, username, email, enc_password, data):
        """Store account info in the store so that the account can be created after verifying the email.
        """
        store = self.site.store.store

        email = email.strip()

        account_key = "account/" + username
        email_key = "account-email/" + email.lower()

        if store.get(account_key):
            raise common.BadData(message="User already exists: %s" % username)

        if store.get(email_key):
            raise common.BadData(message='Email is already used: ' + email)

        now = datetime.datetime.utcnow()
        expires_on = now + datetime.timedelta(days=14)  # 2 weeks

        account_doc = {
            "_key": account_key,
            "type": "account",
            "status": "pending",
            "created_on": now.isoformat(),
            "username": username,
            "lusername": username.lower(),  # lowercase username
            "email": email,
            "enc_password": enc_password,
            "data": data
        }
        email_doc = {
            "_key": email_key,
            "type": "account-email",
            "username": username
        }
        store.put_many([account_doc, email_doc])
Beispiel #10
0
    def POST_update_user(self, site):
        i = input('old_password', new_password=None, email=None)
        a = site.get_account_manager()

        user = a.get_user()
        username = user.key.split("/")[-1]

        status = a.login(username, i.old_password)
        if status == "ok":
            kw = {}
            if i.new_password:
                kw['password'] = i.new_password
            if i.email:
                kw['email'] = i.email
            a.update(username, **kw)
        else:
            raise common.BadData(code=status, message="Invalid password")
Beispiel #11
0
    def _process(self, key, data, prev_data=None):
        self.key = key # hack to make key available when raising exceptions.
        
        
        if 'key' not in data:
            data['key'] = key
            
        if web.ctx.get('infobase_bootstrap', False):
            return data

        assert data['key'] == key

        data = common.parse_query(data)
        self.validate_properties(data)
        prev_data = prev_data and common.parse_query(prev_data)
        
        if not web.ctx.get('disable_permission_check', False) and not self.has_permission(self.author, key):
            raise common.PermissionDenied(message='Permission denied to modify %s' % repr(key))
        
        type = data.get('type')
        if type is None:
            raise common.BadData(message="missing type", at=dict(key=key))
        type = self.process_value(type, self.get_property(None, 'type'))
        type = self.get_thing(type)
        
        # when type is changed, consider as all object is modified and don't compare with prev data.
        if prev_data and prev_data.get('type') != type.key:
            prev_data = None

        data = self.process_data(data, type, prev_data)

        for k in common.READ_ONLY_PROPERTIES:
            data.pop(k, None)
            prev_data and prev_data.pop(k, None)
            
        if data == prev_data:
            return None
        else:
            return data
Beispiel #12
0
def from_json(s):
    try:
        return simplejson.loads(s)
    except ValueError, e:
        raise common.BadData(message="Bad JSON: " + str(e))
Beispiel #13
0
def to_int(value, key):
    try:
        return int(value)
    except:
        raise common.BadData(message="Bad integer value for %s: %s" %
                             (repr(key), repr(value)))
Beispiel #14
0
 def assert_type_required(self):
     type_required = any(c.key not in common.COMMON_PROPERTIES
                         for c in self.conditions
                         if not isinstance(c, Query))
     if type_required and self.get_type() is None:
         raise common.BadData(message="missing 'type' in query")
Beispiel #15
0
 def validate_properties(self, data):
     rx = web.re_compile('^[a-z][a-z0-9_]*$')
     for key in data:
         if not rx.match(key):
             raise common.BadData(message="Bad Property: %s" % repr(key), at=dict(key=self.key))
Beispiel #16
0
                raise common.TypeMismatch(expected_type, type_found, at=at, value=value)
        else:
            if type_found == '/type/string':
                value = common.Reference(value)
    
        type_found = common.find_type(value)
    
        if type_found == '/type/object':
            type_found = self.get_type(value)
            
            # type is not found only when the thing id not found.
            if type_found is None:
                raise common.NotFound(key=unicode(value), at=at)

        if expected_type != type_found:
            raise common.BadData(message='expected %s, found %s' % (property.expected_type.key, type_found), at=at, value=value)
        return value
        

class WriteQueryProcessor:
    def __init__(self, store, author):
        self.store = store
        self.author = author
        
    def process(self, query):
        p = SaveProcessor(self.store, self.author)
        
        for q in serialize(query):
            q = common.parse_query(q)
            
            if not isinstance(q, dict) or q.get('key') is None: