Example #1
0
    async def mutate(self, info, id, title=None, content=None, status=None):
        article = await info.context.loaders.article.load(id)
        if article is None:
            raise Exception('The article does not exist.')

        now = datetime.now()
        fields_set = {'updated_at': now}
        article.updated_at = now

        if title is not None:
            fields_set['title'] = title
            article.title = title
        if content is not None:
            fields_set['content'] = content
            article.content = content
        if status is not None:
            fields_set['status'] = status
            article.status = status
            if status == ArticleStatus.PUBLISHED:
                fields_set['published_at'] = now
                article.published_at = now

        db().articles.update_one({'_id': ObjectId(id)}, {
            '$set': fields_set,
        })

        return article
Example #2
0
    async def mutate(self, info, agent_name, telegram, regions, other=''):
        if not info.context.logged_in:
            raise Exception('Please log in first.')

        me = info.context.user
        if me.faction != Faction.Resistance:
            raise Exception('Access denied.')

        if agent_name == '' or telegram == '' or len(regions) == 0:
            raise Exception(
                'Agent name, telegram username and regions must not be empty.')

        if len(agent_name) > 16:
            raise Exception('Agent name must not more than 16 characters.')
        if len(telegram) > 40:
            raise Exception(
                'Telegram username must not more than 40 characters.')
        if len(other) > 512:
            raise Exception('Descriptions must not more than 512 characters.')

        for ch in agent_name:
            if ch not in allowed_char:
                raise Exception(
                    'Agent name must match the pattern [0-9A-Za-z_]+')
        for ch in telegram:
            if ch not in allowed_char:
                raise Exception(
                    'Telegram username must match the pattern [0-9A-Za-z_]+')

        user = db().users.find_one({'_id': me.id})
        now = datetime.now()

        try:
            join_info = user['join_info']
        except Exception:
            join_info = {'created_at': now, 'status': JoinStatus.PENDING.value}

        if join_info.get('status') == JoinStatus.REJECTED:
            raise Exception('Access denied.')

        join_info = {
            **join_info,
            'agent_name': agent_name,
            'telegram': telegram,
            'regions': regions,
            'other': other,
            'updated_at': now,
        }

        db().users.update_one({'_id': me.id},
                              {'$set': {
                                  'join_info': join_info
                              }})

        info.context.loaders.user.clear(me.id)

        return JoinInfo.from_dict({
            **join_info,
            'user_id': me.id,
        })
Example #3
0
    def get_user_info(self):
        token = self.request.headers.get('Token')

        session = db().sessions.find_one({'token': token})
        if session is None:
            return

        if session['expire'] < time():
            return db().sessions.delete_one({'_id': session['_id']})

        if session.get('new_user'):
            self.new_user = StdClass(
                google_id=session['google_id'],
                email=session['email'],
            )
            return

        user = db().users.find_one(session['user_id'])
        if user is None:
            return

        self.user = StdClass(
            id=user['_id'],
            faction=user['faction'],
            is_admin=user['is_admin'],
        )
        self.logged_in = True
Example #4
0
    async def mutate(self, info, id, title=None, content=None):
        if not info.context.logged_in:
            raise Exception('You must log in to update an article.')

        article = await info.context.loaders.article.load(id)
        if article is None:
            raise Exception('The article does not exist.')

        me = info.context.user
        if not me.is_admin and (me.id != article.author_id
                                or article.status != ArticleStatus.DRAFT):
            raise Exception('Access denied.')

        now = datetime.now()
        fields_set = {'updated_at': now}
        article.updated_at = now

        if title is not None:
            if len(title) == 0:
                raise Exception('The title must not be empty.')
            fields_set['title'] = title
            article.title = title

        if content is not None:
            if len(content) == 0:
                raise Exception('The content must not be empty.')
            fields_set['content'] = content
            article.content = content

        db().articles.update_one({'_id': ObjectId(id)}, {'$set': fields_set})

        return article
Example #5
0
    async def mutate(self, info, name, telegram, regions, other=None):
        if not info.context.logged_in:
            raise Exception('Please log in first.')

        me = info.context.user
        if me.faction != Faction.Resistance:
            raise Exception('Access denied.')

        if name == '' or telegram == '' or len(regions) == 0:
            raise Exception('Name, Telegram and regions must not be empty.')

        join_info = {
            'name': name,
            'telegram': telegram,
            'regions': regions,
            'other': '' if other is None else other,
            'updated_at': datetime.now(),
        }

        db().users.update_one({'_id': me.id}, {
            '$set': {
                'join_info': join_info
            }
        })

        return JoinInfo(
            name=join_info['name'],
            telegram=join_info['telegram'],
            regions=join_info['regions'],
            other=join_info['other'],
            updated_at=str(join_info['updated_at'])
        )
Example #6
0
def insert_token(content):
    for i in range(6):
        token = str(uuid4())
        try:
            db().sessions.insert_one({**content, 'token': token})
            return token
        except DuplicateKeyError:
            if i == 5:
                raise ValueError("You've hit the jackpot!")
Example #7
0
def delete_inactive(cond, active_count):
    active = db().sessions.find({
        **cond, 'expire': {
            '$gt': time()
        }
    }).sort('_id', -1).limit(active_count)

    db().sessions.delete_many({
        **cond,
        '_id': {
            '$nin': [s['_id'] for s in active]
        },
    })
Example #8
0
    def resolve_total_join_info(self, info, status=None):
        cond = {'join_info': {'$ne': None}}

        if status is not None:
            cond['join_info.status'] = status

        return db().users.find(cond).count()
    def post():
        user = db()['users'].find_one(
            {"username": request.values.get('username').lower()})

        if user is not None:
            valid_username = request.values.get(
                'username').lower() == user['username'].lower()
            valid_password = bcrypt.hashpw(
                request.values.get('password').encode('utf-8'),
                user['password']) == user['password']

            if valid_username and valid_password:
                token = jwt.JWT(header={'alg': 'HS256'},
                                claims={
                                    'usr': user['username'],
                                    'iat': int(time.time()),
                                    'exp': int(time.time() + 900)
                                })
                token.make_signed_token(
                    jwk.JWK(**json.loads(config('UL_KEY'))))
                return Response(json.dumps({
                    "type": "success",
                    "msg": "Login success.",
                    "jws": token.serialize()
                }),
                                mimetype='application/json'), 200
        return Response(json.dumps({"msg":
                                    "Invalid username and/or password"}),
                        mimetype='application/json'), 403
Example #10
0
    def batch_load_fn(self, keys):
        keys = [ObjectId(k) for k in keys]

        users = {}
        for result in db().users.find({'_id': {'$in': keys}}):
            if result.get('join_info') is None:
                join_info = None
            else:
                join_info = JoinInfo.from_dict({
                    **result['join_info'],
                    'user_id':
                    result['_id'],
                })

            users[result['_id']] = user.User(id=result['_id'],
                                             google_id=result['google_id'],
                                             email=result['email'],
                                             avatar=nstr(result.get('avatar')),
                                             is_admin=result['is_admin'],
                                             name=result['name'],
                                             faction=result['faction'],
                                             created_at=str(
                                                 result['created_at']),
                                             join_info=join_info)

        return Promise.resolve([users.get(key) for key in keys])
    def mutate(self, info, name, faction):
        if info.context.logged_in:
            raise Exception('You have been registered.')

        new_user = info.context.new_user
        if new_user is None:
            raise Exception('Please sign in with Google Account first.')

        name_len = len(name)
        if name_len < 3 or name_len > 16:
            raise Exception('Invalid name: 3 <= len(name) <= 16.')

        try:
            _ = Faction(faction)
        except ValueError:
            raise Exception('Invalid faction.')

        now = datetime.now()

        result = db().users.insert_one({
            'google_id': new_user.google_id,
            'email': new_user.email,
            'avatar': new_user.avatar,
            'is_admin': False,
            'name': name,
            'faction': faction,
            'created_at': now
        })

        token = info.context.request.headers.get('Token')
        db().sessions.replace_one({'token': token}, {
            'token': token,
            'user_id': result.inserted_id,
            'expire': now.timestamp() + 604800,
        })

        return User(
            id=result.inserted_id,
            google_id=new_user.google_id,
            email=new_user.email,
            avatar=new_user.avatar,
            is_admin=False,
            name=name,
            faction=faction,
            created_at=str(now),
        )
Example #12
0
    def batch_load_fn(self, keys):
        keys = [ObjectId(k) for k in keys]

        articles = {}
        for result in db().articles.find({'_id': {'$in': keys}}):
            article = lib.schemas.types.article.Article.from_dict(result)
            articles[result['_id']] = article

        return Promise.resolve([articles.get(key) for key in keys])
    async def mutate(self, info, user_id, status=None, comment=None):
        print(user_id)

        fields_set = {}
        if status is not None:
            fields_set['join_info.status'] = status
        if comment is not None:
            fields_set['join_info.comment'] = comment

        db().users.update_one({'_id': ObjectId(user_id)}, {
            '$set': fields_set,
        })

        user = db().users.find_one({'_id': ObjectId(user_id)})

        return JoinInfo.from_dict({
            **user['join_info'],
            'user_id': user_id,
        })
    async def mutate(self, info, title, content):
        if not info.context.logged_in:
            raise Exception('You must log in to create an article.')

        user = info.context.user
        if not user.is_admin:
            count = db().articles.find({
                'author_id': user.id,
                'published_at': None
            }).count()
            if count >= 3:
                raise Exception(
                    'You have already submitted 3 drafts. Try completing and publishing them.'
                )

        if len(title) == 0:
            raise Exception('The title must not be empty.')
        if len(title) > 100:
            raise Exception('Tht title must not more than 64 words.')
        if len(content) == 0:
            raise Exception('The content must not be empty.')

        now = datetime.now()
        result = db().articles.insert_one({
            'author_id': user.id,
            'title': title,
            'content': content,
            'created_at': now,
            'updated_at': now,
        })

        article = Article(
            id=result.inserted_id,
            author_id=user.id,
            title=title,
            content=content,
            tags=[],
            created_at=now,
            updated_at=now,
            published_at=None,
        )

        return article
Example #15
0
    def resolve_list_articles(self, info, count, offset, status=None):
        cond = {}
        if status is not None:
            cond['status'] = status

        articles = []
        results = db().articles.find(cond).skip(offset).limit(count)

        for result in results:
            articles.append(Article.from_dict(result))

        return articles
Example #16
0
    async def resolve_join_info(self, info):
        if not info.context.logged_in:
            raise Exception('You have not been logged in.')

        user_id = info.context.user.id
        result = db().users.find_one(user_id).get('join_info')

        return None if result is None else JoinInfo(
            name=result['name'],
            telegram=result['telegram'],
            regions=result['regions'],
            other=result['other'],
            updated_at=str(result['updated_at']))
Example #17
0
    def resolve_latest_articles(self, info, count, offset):
        articles = []

        results = db().articles\
            .find({'status': ArticleStatus.PUBLISHED.value})\
            .sort('_id', -1)\
            .skip(offset)\
            .limit(count)

        for result in results:
            article = Article.from_dict(result)
            filter_article_fields(article, info.context)
            articles.append(article)

        return articles
Example #18
0
    def batch_load_fn(self, keys):
        keys = [ObjectId(k) for k in keys]

        users = {}
        for result in db().users.find({'_id': {'$in': keys}}):
            users[result['_id']] = lib.schemas.types.user.User(
                id=result['_id'],
                google_id=result['google_id'],
                email=result['email'],
                is_admin=result['is_admin'],
                name=result['name'],
                faction=result['faction'],
                created_at=nstr(result['created_at']),
            )

        return Promise.resolve([users.get(key) for key in keys])
Example #19
0
    def batch_load_fn(self, keys):
        keys = [ObjectId(k) for k in keys]

        articles = {}
        for key in keys:
            articles[key] = []

        for result in db().articles.find({
                'author_id': {
                    '$in': keys
                }
        }).sort('_id', -1):
            article = lib.schemas.types.article.Article.from_dict(result)
            articles[result['author_id']].append(article)

        return Promise.resolve([articles[key] for key in keys])
Example #20
0
    def resolve_list_join_info(self, info, count, offset, status=None):
        cond = {'join_info': {'$ne': None}}

        if status is not None:
            cond['join_info.status'] = status

        join_info_list = []
        results = db().users.find(cond).skip(offset).limit(count)

        for result in results:
            join_info_list.append(
                JoinInfo.from_dict({
                    **result['join_info'],
                    'user_id':
                    result['_id'],
                }))

        return join_info_list
Example #21
0
def auth():
    try:
        google_token = request.args['google_token']
        id_info = id_token.verify_oauth2_token(google_token,
                                               requests.Request(),
                                               config.GOOGLE_CLIENT_ID)

        if id_info['iss'] not in [
                'accounts.google.com', 'https://accounts.google.com'
        ]:
            raise ValueError('Wrong issuer.')

        google_id = id_info['sub']

        user = db().users.find_one({'google_id': google_id})
        if user is None:
            token = insert_token({
                'new_user': True,
                'google_id': google_id,
                'email': id_info['email'],
                'avatar': id_info['picture'],
                'expire': time() + 604800,
            })
            delete_inactive({'google_id': google_id}, 3)

            return '{"token":"' + token + '","newUser":true}'

        token = insert_token({
            'user_id': user['_id'],
            'expire': time() + 604800,
        })
        delete_inactive({'user_id': user['_id']}, 5)

        return '{"token":"' + token + '"}'
    except Exception:
        abort(401)
Example #22
0
    def resolve_total_articles(self, info, status=None):
        cond = {}
        if status is not None:
            cond['status'] = status

        return db().articles.find(cond).count()
Example #23
0
 def resolve_article_count(self, info):
     return db().articles.count()