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
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, })
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
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
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']) )
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!")
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] }, })
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
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), )
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
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
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']))
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
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])
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])
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
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)
def resolve_total_articles(self, info, status=None): cond = {} if status is not None: cond['status'] = status return db().articles.find(cond).count()
def resolve_article_count(self, info): return db().articles.count()