diff --git a/auth/email.py b/auth/email.py
index 9c9b7220..dcc815af 100644
--- a/auth/email.py
+++ b/auth/email.py
@@ -14,7 +14,7 @@ email_templates = {"confirm_email" : "", "auth_email" : "", "reset_password_emai
def load_email_templates():
for name in email_templates:
- filename = "auth/templates/%s.tmpl" % name # TODO: check path
+ filename = "auth/templates/%s.tmpl" % name
with open(filename) as f:
email_templates[name] = f.read()
print("[auth.email] templates loaded")
diff --git a/auth/validations.py b/auth/validations.py
index 38a2f620..fc2b7353 100644
--- a/auth/validations.py
+++ b/auth/validations.py
@@ -25,5 +25,3 @@ class CreateUser(BaseModel):
# age: Optional[int]
# phone: Optional[Text]
password: Optional[Text]
-
-# TODO: update validations
diff --git a/main.py b/main.py
index 9fa77251..1c1cb9ed 100644
--- a/main.py
+++ b/main.py
@@ -40,7 +40,7 @@ async def shutdown():
await redis.disconnect()
routes = [
- Route("/oauth/{provider}", endpoint=oauth_login), # TODO: isolate auth microservice
+ Route("/oauth/{provider}", endpoint=oauth_login),
Route("/oauth_authorize", endpoint=oauth_authorize),
Route("/email_authorize", endpoint=email_authorize)
]
diff --git a/migration/extract.py b/migration/extract.py
index 0c09ae0c..eff2f22f 100644
--- a/migration/extract.py
+++ b/migration/extract.py
@@ -9,11 +9,11 @@ s3 = 'https://discours-io.s3.amazonaws.com/'
cdn = 'https://assets.discours.io'
def replace_tooltips(body):
- # FIXME: if you prefer regexp
+ # change if you prefer regexp
newbody = body
matches = list(re.finditer(TOOLTIP_REGEX, body, re.IGNORECASE | re.MULTILINE))[1:]
for match in matches:
- newbody = body.replace(match.group(1), '
stuff... data = "\n" + data diff --git a/migration/tables/comments.py b/migration/tables/comments.py index cce282d3..648170b2 100644 --- a/migration/tables/comments.py +++ b/migration/tables/comments.py @@ -47,8 +47,8 @@ def migrate(entry, storage): } ''' reaction_dict = {} - # FIXME: comment_dict['createdAt'] = ts if not entry.get('createdAt') else date_parse(entry.get('createdAt')) - # print('[migration] comment original date %r' % entry.get('createdAt')) + reaction_dict['createdAt'] = ts if not entry.get('createdAt') else date_parse(entry.get('createdAt')) + print('[migration] reaction original date %r' % entry.get('createdAt')) # print('[migration] comment date %r ' % comment_dict['createdAt']) reaction_dict['body'] = html2text(entry.get('body', '')) reaction_dict['oid'] = entry['_id'] diff --git a/migration/tables/content_items.py b/migration/tables/content_items.py index 0fa23961..849df0bb 100644 --- a/migration/tables/content_items.py +++ b/migration/tables/content_items.py @@ -118,8 +118,8 @@ def migrate(entry, storage): s = object() shout_dict = r.copy() user = None - del shout_dict['topics'] # FIXME: AttributeError: 'str' object has no attribute '_sa_instance_state' - #del shout_dict['rating'] # FIXME: TypeError: 'rating' is an invalid keyword argument for Shout + del shout_dict['topics'] # NOTE: AttributeError: 'str' object has no attribute '_sa_instance_state' + #del shout_dict['rating'] # NOTE: TypeError: 'rating' is an invalid keyword argument for Shout #del shout_dict['ratings'] email = userdata.get('email') slug = userdata.get('slug') diff --git a/orm/collection.py b/orm/collection.py index 26c5eb39..95b8a6f4 100644 --- a/orm/collection.py +++ b/orm/collection.py @@ -17,4 +17,6 @@ class Collection(Base): title: str = Column(String, nullable=False, comment="Title") body: str = Column(String, nullable=True, comment="Body") pic: str = Column(String, nullable=True, comment="Picture") + createdAt: datetime = Column(DateTime, default=datetime.now, comment="Created At") + createdBy: str = Column(ForeignKey('user.id'), comment="Created By") diff --git a/orm/notification.py b/orm/notification.py index d41bd874..1996f700 100644 --- a/orm/notification.py +++ b/orm/notification.py @@ -8,4 +8,4 @@ class Notification(Base): template: str = Column(String, nullable = False) variables: JSONType = Column(JSONType, nullable = True) # [, .. ] - # FIXME looks like frontend code \ No newline at end of file + # looks like frontend code \ No newline at end of file diff --git a/resolvers/collection.py b/resolvers/collection.py new file mode 100644 index 00000000..c00c3ac5 --- /dev/null +++ b/resolvers/collection.py @@ -0,0 +1,80 @@ +from orm.collection import Collection, CollectionFollower +from base.orm import local_session +from orm.user import User +from base.resolvers import mutation, query +from auth.authenticate import login_required +from datetime import datetime +from typing import Collection, List +from sqlalchemy import and_ + +@mutation.field("createCollection") +@login_required +async def create_collection(_, info, input): + auth = info.context["request"].auth + user_id = auth.user_id + collection = Collection.create( + slug = input.get('slug', ''), + title = input.get('title', ''), + desc = input.get('desc', ''), + pic = input.get('pic', '') + ) + + return {"collection": collection} + +@mutation.field("updateCollection") +@login_required +async def update_collection(_, info, input): + auth = info.context["request"].auth + user_id = auth.user_id + collection_slug = input.get('slug', '') + with local_session() as session: + owner = session.query(User).filter(User.id == user_id) # note list here + collection = session.query(Collection).filter(Collection.slug == collection_slug).first() + editors = [e.slug for e in collection.editors] + if not collection: + return {"error": "invalid collection id"} + if collection.createdBy not in (owner + editors): + return {"error": "access denied"} + collection.title = input.get('title', '') + collection.desc = input.get('desc', '') + collection.pic = input.get('pic', '') + collection.updatedAt = datetime.now() + session.commit() + +@mutation.field("deleteCollection") +@login_required +async def delete_collection(_, info, slug): + auth = info.context["request"].auth + user_id = auth.user_id + with local_session() as session: + collection = session.query(Collection).filter(Collection.slug == slug).first() + if not collection: + return {"error": "invalid collection slug"} + if collection.owner != user_id: + return {"error": "access denied"} + collection.deletedAt = datetime.now() + session.commit() + + return {} + +@query.field("getCollection") +async def get_collection(_, info, userslug, colslug): + with local_session() as session: + user = session.query(User).filter(User.slug == userslug).first() + if user: + collection = session.\ + query(Collection).\ + where(and_(Collection.createdBy == user.id, Collection.slug == colslug)).\ + first() + if not collection: + return {"error": "collection not found"} + return collection + +@query.field("getMyColelctions") +@login_required +async def get_collections(_, info): + auth = info.context["request"].auth + user_id = auth.user_id + with local_session() as session: + collections = session.query(Collection).when(Collection.createdBy == user_id).all() + return collections \ No newline at end of file diff --git a/resolvers/reactions.py b/resolvers/reactions.py index fd1a1fe7..2e68c7c1 100644 --- a/resolvers/reactions.py +++ b/resolvers/reactions.py @@ -75,7 +75,7 @@ async def update_reaction(_, info, inp): reaction.body = inp['body'] reaction.updatedAt = datetime.now() if reaction.kind != inp['kind']: - # TODO: change mind detection + # NOTE: change mind detection can be here pass if inp.get('range'): reaction.range = inp.get('range') diff --git a/resolvers/zine.py b/resolvers/zine.py index 931cf369..1bce3936 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -51,7 +51,7 @@ async def view_shout(_, info, slug): @query.field("getShoutBySlug") async def get_shout_by_slug(_, info, slug): shout = None - # TODO: append captions anyhow + # FIXME: append captions anyhow with local_session() as session: shout = session.query(Shout).\ options([ @@ -65,7 +65,7 @@ async def get_shout_by_slug(_, info, slug): if not shout: print(f"[resolvers.zine] error: shout with slug {slug} not exist") - return {} #TODO return error field + return {"error" : "shout not found"} return shout diff --git a/schema.graphql b/schema.graphql index b527543b..a4128701 100644 --- a/schema.graphql +++ b/schema.graphql @@ -189,9 +189,6 @@ type Mutation { unfollow(what: FollowingEntity!, slug: String!): Result! # TODO: transform reaction with body to shout - - # NOTE: so-named 'collections' are tuned feeds - # TODO: Feed entity and CRUM: createFeed updateFeed deleteFeed mergeFeeds } ################################### Query @@ -229,7 +226,7 @@ type Query { shoutsByCommunities(slugs: [String]!, page: Int!, size: Int!): [Shout]! myCandidates(page: Int!, size: Int!): [Shout]! # test topViewed(page: Int!, size: Int!): [Shout]! - # TODO: topReacted(page: Int!, size: Int!): [Shout]! + # topReacted(page: Int!, size: Int!): [Shout]! topMonth(page: Int!, size: Int!): [Shout]! topOverall(page: Int!, size: Int!): [Shout]! recentPublished(page: Int!, size: Int!): [Shout]! # homepage diff --git a/server.py b/server.py index 6f28f3ef..1e211bb7 100644 --- a/server.py +++ b/server.py @@ -4,7 +4,8 @@ from settings import PORT import sys if __name__ == '__main__': - x = sys.argv[1] or "" + x = '' + if len(sys.argv) > 1: x = sys.argv[1] if x == "dev": print("DEV MODE") headers = [ diff --git a/services/auth/users.py b/services/auth/users.py index 89393380..5ff6d4c4 100644 --- a/services/auth/users.py +++ b/services/auth/users.py @@ -12,7 +12,6 @@ class UserStorage: self = UserStorage users = session.query(User).\ options(selectinload(User.roles), selectinload(User.ratings)).all() - # TODO: add shouts and reactions counters self.users = dict([(user.id, user) for user in users]) print('[service.auth] %d users' % len(self.users)) diff --git a/services/stat/reacted.py b/services/stat/reacted.py index 95711215..87ceecda 100644 --- a/services/stat/reacted.py +++ b/services/stat/reacted.py @@ -48,7 +48,6 @@ class ReactedStorage: self.this_day_reactions[shout] = reaction print('[service.reacted] watching %d shouts' % len(reactions)) - # TODO: add reactions ? @staticmethod async def get_shout(shout_slug): diff --git a/services/stat/viewed.py b/services/stat/viewed.py index 46700240..a0ac5956 100644 --- a/services/stat/viewed.py +++ b/services/stat/viewed.py @@ -17,7 +17,6 @@ class ViewedByDay(Base): class ViewedStorage: viewed = { 'shouts': {}, - # TODO: ? 'reactions': {}, 'topics': {} # TODO: get sum views for all shouts in topic } this_day_views = {} @@ -43,7 +42,6 @@ class ViewedStorage: self.this_day_views[shout] = view print('[service.viewed] watching %d shouts' % len(views)) - # TODO: add reactions ? @staticmethod async def get_shout(shout_slug): diff --git a/services/zine/shoutauthor.py b/services/zine/shoutauthor.py index 7858b143..99787637 100644 --- a/services/zine/shoutauthor.py +++ b/services/zine/shoutauthor.py @@ -20,7 +20,8 @@ class ShoutAuthorStorage: self.authors_by_shout[shout].append(user) else: self.authors_by_shout[shout] = [user] - print('[service.shoutauthor] %d shouts ' % len(self.authors_by_shout)) + print('[service.shoutauthor] %d authors ' % len(self.authors_by_shout)) + # FIXME: [service.shoutauthor] 4251 authors @staticmethod async def get_authors(shout):