Example #1
0
 def to_api_dict(self, authorizer: Authorizer = None):
     data = {
         'completed':
         self.completed,
         'created':
         int(time.time()),
         'objective':
         self.objective_key,
         'stage':
         split_key(self.objective_key)[0],
         'area':
         split_key(self.objective_key)[1],
         'score':
         self.score,
         'line':
         int(split_key(self.objective_key)[2].split('.')[0]),
         'subline':
         int(split_key(self.objective_key)[2].split('.')[1]),
         'original-objective':
         self.original_objective,
         'personal-objective':
         self.personal_objective,
         'tasks': [{
             'completed': task.completed,
             'description': task.description,
         } for task in self.tasks],
     }
     if authorizer is not None:
         data['token'] = self.generate_token(authorizer,
                                             duration=timedelta(days=1))
     return data
def complete_active_task(event: HTTPEvent) -> JSONResponse:
    sub = event.params['sub']

    if event.authorizer.sub != sub and not event.authorizer.is_scouter:
        return JSONResponse.generate_error(
            HTTPError.FORBIDDEN,
            "You have no access to this resource with this user")
    completed_task = TasksService.complete_active_task(event.authorizer)
    if completed_task is None:
        return JSONResponse.generate_error(HTTPError.NOT_FOUND,
                                           "No active task found")

    area = split_key(completed_task['objective'])[1]

    response = JSONResponse({
        'message':
        'Completed task',
        'task':
        completed_task,
        'reward':
        RewardsFactory.get_reward_token_by_reason(
            authorizer=event.authorizer,
            area=area,
            reason=RewardReason.COMPLETE_OBJECTIVE),
    })
    LogsService.create(
        event.authorizer.sub,
        LogTag.COMPLETED.join(completed_task['objective'].upper()),
        'Completed an objective!', {})
    return response
    def update_avatar(cls, user_sub: str, avatar: dict):
        interface = cls.get_interface()

        parts_ids = [part_id for part_id in set(avatar.values()) if part_id is not None]
        if len(parts_ids) > 0:
            logs = LogsService.batch_get(
                [LogKey(sub=user_sub, tag=join_key('REWARD', 'AVATAR', part_id)) for part_id in
                 parts_ids],
                attributes=['data', 'tag'])
            if len(logs) != len(parts_ids):
                raise NotFoundException("An avatar part was not found")
        else:
            logs = []

        avatar_parts = {int(split_key(log.tag)[-1]): Reward.from_api_map(log.data).to_api_map() for log in logs}
        new_avatar = {
            'left_eye': avatar_parts.get(avatar.get('left_eye')),
            'right_eye': avatar_parts.get(avatar.get('right_eye')),
            "mouth": avatar_parts.get(avatar.get('mouth')),
            "top": avatar_parts.get(avatar.get('top')),
            "bottom": avatar_parts.get(avatar.get('bottom')),
            "neckerchief": avatar_parts.get(avatar.get('neckerchief'))
        }
        interface.update(user_sub, updates={'avatar': new_avatar})
        return new_avatar
Example #4
0
def create_log(event: HTTPEvent):
    user_sub: str = event.params['sub']
    tag: str = event.params['tag'].upper()

    if event.authorizer.sub != user_sub:
        raise ForbiddenException("Only the same user can create logs")
    parent_tag = LogTag.from_short(split_key(tag)[0])
    if parent_tag not in USER_VALID_TAGS:
        raise ForbiddenException(f"A user can only create logs with the following tags: {USER_VALID_TAGS}")

    body = event.json

    log = body['log']
    data = body.get('data')

    if len(body) > 1024:
        raise InvalidException(f"A log can't have more than 1024 characters")

    if data is not None:
        if len(json.dumps(data)) > 2048:
            raise InvalidException(f"Log data is too big")

    response_body = {}

    if parent_tag == LogTag.PROGRESS:
        if tag != parent_tag.short:
            raise InvalidException(f"A progress log tag can't be compound")
        if body.get('token') is None:
            raise InvalidException(f"To post a PROGRESS log you must provide the task token")

        objective = TasksService.get_task_token_objective(body['token'], authorizer=event.authorizer)
        tag = join_key(LogTag.PROGRESS.value, objective).upper()

        now = int(datetime.now(timezone.utc).timestamp() * 1000)
        last_progress_log = LogsService.get_last_log_with_tag(event.authorizer.sub, tag.upper())

        if last_progress_log is None or now - last_progress_log.timestamp > 24 * 60 * 60 * 1000:
            response_body['token'] = RewardsFactory.get_reward_token_by_reason(authorizer=event.authorizer,
                                                                               area=split_key(objective)[1],
                                                                               reason=RewardReason.PROGRESS_LOG)

    log = LogsService.create(user_sub, tag, log_text=log, data=body.get('data'), append_timestamp_to_tag=True)
    response_body['item'] = log.to_api_map()

    return JSONResponse(body=response_body)
Example #5
0
def query_logs(event: HTTPEvent):
    user_sub = event.params['sub']
    tag = LogTag.normalize(split_key(event.params['tag'])).upper() if event.params.get('tag') else None

    limit = event.queryParams.get('limit', 25)
    if not isinstance(limit, int) or limit > 100:
        raise InvalidException("Limit must be an integer and lower or equal than 100")

    logs = LogsService.query(user_sub, tag, limit=limit)
    return JSONResponse(body=QueryResult.from_list([log.to_api_map() for log in logs]).as_dict())
Example #6
0
 def to_api_map(self):
     tag: str = self.tag.name if isinstance(self.tag, LogTag) else self.tag
     long_tag: str = tag if not self.append_timestamp else join_key(
         tag, self.timestamp)
     data = {
         "tag": self.parent_tag.normalize(split_key(long_tag), short=True),
         "user": self.sub,
         "log": self.log,
         'timestamp': self.timestamp
     }
     if self.data is not None:
         data['data'] = self.data
     return data
Example #7
0
    def normalize(tag: List[str], short=False):
        parent_tag_full = LogTag.from_tag(tag, short=False)
        parent_tag = LogTag.from_tag(
            tag, short=True) if parent_tag_full is None else parent_tag_full
        if parent_tag is None:
            raise InvalidException(f'Tag {join_key(*tag)} does not exist')
        source_is_short = parent_tag_full is None

        tag_body = tag[
            1 if source_is_short else len(split_key(parent_tag.value)):]
        if not short:
            return join_key(parent_tag.value, *tag_body)
        else:
            return join_key(parent_tag.short, *tag_body)
    def from_db_map(beneficiary: dict):
        if beneficiary is None:
            return None

        from core.services.tasks import Task

        user_sub = beneficiary.get("user")

        district_group = beneficiary.get("group")
        district, group = district_group.split("::") if district_group is not None else (None, None)

        unit_user = beneficiary.get("unit-user")
        unit = split_key(unit_user)[0] if unit_user is not None else None

        full_name = beneficiary.get("full-name")
        nickname = beneficiary.get("nickname")

        raw_birthdate = beneficiary.get("birthdate")
        birthdate = datetime.strptime(raw_birthdate, "%d-%m-%Y") if raw_birthdate is not None else None

        score = beneficiary.get("score")
        score = {area: int(score.get(area, 0)) for area in VALID_AREAS} if score is not None else None

        n_tasks = beneficiary.get("n_tasks")
        n_tasks = {area: int(n_tasks.get(area, 0)) for area in VALID_AREAS} if n_tasks is not None else None

        target = beneficiary.get("target")
        target = Task.from_db_dict(target) if target is not None else None

        bought_items = beneficiary.get("bought_items", {})
        set_base_tasks = beneficiary.get("set_base_tasks", False)

        generated_token_last = int(beneficiary.get("generated_token_last", -1))
        n_claimed_tokens = int(beneficiary.get("n_claimed_tokens", -1))

        profile_picture = beneficiary.get('profile_picture')

        return Beneficiary(user_sub=user_sub, full_name=full_name, nickname=nickname, district=district, group=group,
                           unit=unit, score=score, n_tasks=n_tasks, birthdate=birthdate, target=target,
                           bought_items=bought_items, set_base_tasks=set_base_tasks, n_claimed_tokens=n_claimed_tokens,
                           generated_token_last=generated_token_last, profile_picture=profile_picture)
    def clear_active_task(cls, authorizer: Authorizer,
                          return_values: UpdateReturnValues = UpdateReturnValues.UPDATED_OLD,
                          receive_score=False
                          ):
        interface = cls.get_interface()
        updates = {'target': None}
        add_to = None
        if receive_score:
            beneficiary = BeneficiariesService.get(authorizer.sub, ["target"])

            if beneficiary.target is None:
                return None
            score = ScoreConfiguration.instance().base_score
            area = split_key(beneficiary.target.objective_key)[1]
            add_to = {
                f'score.{area}': score,
                f'n_tasks.{area}': 1
            }

        try:
            return interface.update(authorizer.sub, updates, None, return_values=return_values,
                                    add_to=add_to, conditions=Attr('target').ne(None))["Attributes"]
        except interface.client.exceptions.ConditionalCheckFailedException:
            raise InvalidException('No active target')
Example #10
0
 def short(self):
     return split_key(self.value)[-1]
Example #11
0
 def tags(self) -> List[str]:
     return split_key(self.tag)
Example #12
0
 def process_beneficiary_code(code: str):
     num, district, group = split_key(code)
     return {"district": district, "code": num, "group": group}