server-cli-todo-cleanup

This commit is contained in:
tonyrewin 2022-08-11 14:22:10 +03:00
parent 0ba5047ff9
commit f13f40c89a
18 changed files with 106 additions and 33 deletions

View File

@ -14,7 +14,7 @@ email_templates = {"confirm_email" : "", "auth_email" : "", "reset_password_emai
def load_email_templates(): def load_email_templates():
for name in 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: with open(filename) as f:
email_templates[name] = f.read() email_templates[name] = f.read()
print("[auth.email] templates loaded") print("[auth.email] templates loaded")

View File

@ -25,5 +25,3 @@ class CreateUser(BaseModel):
# age: Optional[int] # age: Optional[int]
# phone: Optional[Text] # phone: Optional[Text]
password: Optional[Text] password: Optional[Text]
# TODO: update validations

View File

@ -40,7 +40,7 @@ async def shutdown():
await redis.disconnect() await redis.disconnect()
routes = [ routes = [
Route("/oauth/{provider}", endpoint=oauth_login), # TODO: isolate auth microservice Route("/oauth/{provider}", endpoint=oauth_login),
Route("/oauth_authorize", endpoint=oauth_authorize), Route("/oauth_authorize", endpoint=oauth_authorize),
Route("/email_authorize", endpoint=email_authorize) Route("/email_authorize", endpoint=email_authorize)
] ]

View File

@ -9,11 +9,11 @@ s3 = 'https://discours-io.s3.amazonaws.com/'
cdn = 'https://assets.discours.io' cdn = 'https://assets.discours.io'
def replace_tooltips(body): def replace_tooltips(body):
# FIXME: if you prefer regexp # change if you prefer regexp
newbody = body newbody = body
matches = list(re.finditer(TOOLTIP_REGEX, body, re.IGNORECASE | re.MULTILINE))[1:] matches = list(re.finditer(TOOLTIP_REGEX, body, re.IGNORECASE | re.MULTILINE))[1:]
for match in matches: for match in matches:
newbody = body.replace(match.group(1), '<Tooltip text="' + match.group(2) + '" />') # FIXME: doesn't work newbody = body.replace(match.group(1), '<Tooltip text="' + match.group(2) + '" />') # NOTE: doesn't work
if len(matches) > 0: if len(matches) > 0:
print('[extract] found %d tooltips' % len(matches)) print('[extract] found %d tooltips' % len(matches))
return newbody return newbody
@ -54,7 +54,7 @@ cache = {}
def reextract_images(body, oid): def reextract_images(body, oid):
# FIXME: if you prefer regexp # change if you prefer regexp
matches = list(re.finditer(IMG_REGEX, body, re.IGNORECASE | re.MULTILINE))[1:] matches = list(re.finditer(IMG_REGEX, body, re.IGNORECASE | re.MULTILINE))[1:]
i = 0 i = 0
for match in matches: for match in matches:
@ -63,7 +63,7 @@ def reextract_images(body, oid):
name = oid + str(i) name = oid + str(i)
link = public + '/upload/image-' + name + '.' + ext link = public + '/upload/image-' + name + '.' + ext
img = match.group(4) img = match.group(4)
title = match.group(1) # FIXME: this is not the title title = match.group(1) # NOTE: this is not the title
if img not in cache: if img not in cache:
content = base64.b64decode(img + '==') content = base64.b64decode(img + '==')
print(str(len(img)) + ' image bytes been written') print(str(len(img)) + ' image bytes been written')
@ -72,7 +72,7 @@ def reextract_images(body, oid):
i += 1 i += 1
else: else:
print('[extract] image cached ' + cache[img]) print('[extract] image cached ' + cache[img])
body.replace(str(match), '![' + title + '](' + cdn + link + ')') # FIXME: this does not work body.replace(str(match), '![' + title + '](' + cdn + link + ')') # WARNING: this does not work
return body return body
IMAGES = { IMAGES = {

View File

@ -30,8 +30,7 @@ from .utils import (
__version__ = (2020, 1, 16) __version__ = (2020, 1, 16)
# TODO: # TODO: Support decoded entities with UNIFIABLE.
# Support decoded entities with UNIFIABLE.
class HTML2Text(html.parser.HTMLParser): class HTML2Text(html.parser.HTMLParser):
@ -503,7 +502,7 @@ class HTML2Text(html.parser.HTMLParser):
self.handle_emphasis(start, tag_style, parent_style) self.handle_emphasis(start, tag_style, parent_style)
if tag in ["kbd", "code", "tt"] and not self.pre: if tag in ["kbd", "code", "tt"] and not self.pre:
self.o("`") # TODO: `` `this` `` self.o("`") # `` `this` ``
self.code = not self.code self.code = not self.code
if tag == "abbr": if tag == "abbr":
@ -681,7 +680,7 @@ class HTML2Text(html.parser.HTMLParser):
# Indent two spaces per list, except use three spaces for an # Indent two spaces per list, except use three spaces for an
# unordered list inside an ordered list. # unordered list inside an ordered list.
# https://spec.commonmark.org/0.28/#motivation # https://spec.commonmark.org/0.28/#motivation
# TODO: line up <ol><li>s > 9 correctly. # WARNING: does not line up <ol><li>s > 9 correctly.
parent_list = None parent_list = None
for list in self.list: for list in self.list:
self.o( self.o(
@ -761,7 +760,6 @@ class HTML2Text(html.parser.HTMLParser):
self.out("\n[/code]") self.out("\n[/code]")
self.p() self.p()
# TODO: Add docstring for these one letter functions
def pbr(self) -> None: def pbr(self) -> None:
"Pretty print has a line break" "Pretty print has a line break"
if self.p_p == 0: if self.p_p == 0:
@ -807,7 +805,7 @@ class HTML2Text(html.parser.HTMLParser):
return return
if self.startpre: if self.startpre:
# self.out(" :") #TODO: not output when already one there # self.out(" :") # not an output when already one there
if not data.startswith("\n") and not data.startswith("\r\n"): if not data.startswith("\n") and not data.startswith("\r\n"):
# <pre>stuff... # <pre>stuff...
data = "\n" + data data = "\n" + data

View File

@ -47,8 +47,8 @@ def migrate(entry, storage):
} }
''' '''
reaction_dict = {} reaction_dict = {}
# FIXME: comment_dict['createdAt'] = ts if not entry.get('createdAt') else date_parse(entry.get('createdAt')) reaction_dict['createdAt'] = ts if not entry.get('createdAt') else date_parse(entry.get('createdAt'))
# print('[migration] comment original date %r' % entry.get('createdAt')) print('[migration] reaction original date %r' % entry.get('createdAt'))
# print('[migration] comment date %r ' % comment_dict['createdAt']) # print('[migration] comment date %r ' % comment_dict['createdAt'])
reaction_dict['body'] = html2text(entry.get('body', '')) reaction_dict['body'] = html2text(entry.get('body', ''))
reaction_dict['oid'] = entry['_id'] reaction_dict['oid'] = entry['_id']

View File

@ -118,8 +118,8 @@ def migrate(entry, storage):
s = object() s = object()
shout_dict = r.copy() shout_dict = r.copy()
user = None user = None
del shout_dict['topics'] # FIXME: AttributeError: 'str' object has no attribute '_sa_instance_state' del shout_dict['topics'] # NOTE: 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['rating'] # NOTE: TypeError: 'rating' is an invalid keyword argument for Shout
#del shout_dict['ratings'] #del shout_dict['ratings']
email = userdata.get('email') email = userdata.get('email')
slug = userdata.get('slug') slug = userdata.get('slug')

View File

@ -17,4 +17,6 @@ class Collection(Base):
title: str = Column(String, nullable=False, comment="Title") title: str = Column(String, nullable=False, comment="Title")
body: str = Column(String, nullable=True, comment="Body") body: str = Column(String, nullable=True, comment="Body")
pic: str = Column(String, nullable=True, comment="Picture") 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")

View File

@ -8,4 +8,4 @@ class Notification(Base):
template: str = Column(String, nullable = False) template: str = Column(String, nullable = False)
variables: JSONType = Column(JSONType, nullable = True) # [ <var1>, .. ] variables: JSONType = Column(JSONType, nullable = True) # [ <var1>, .. ]
# FIXME looks like frontend code # looks like frontend code

80
resolvers/collection.py Normal file
View File

@ -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

View File

@ -75,7 +75,7 @@ async def update_reaction(_, info, inp):
reaction.body = inp['body'] reaction.body = inp['body']
reaction.updatedAt = datetime.now() reaction.updatedAt = datetime.now()
if reaction.kind != inp['kind']: if reaction.kind != inp['kind']:
# TODO: change mind detection # NOTE: change mind detection can be here
pass pass
if inp.get('range'): if inp.get('range'):
reaction.range = inp.get('range') reaction.range = inp.get('range')

View File

@ -51,7 +51,7 @@ async def view_shout(_, info, slug):
@query.field("getShoutBySlug") @query.field("getShoutBySlug")
async def get_shout_by_slug(_, info, slug): async def get_shout_by_slug(_, info, slug):
shout = None shout = None
# TODO: append captions anyhow # FIXME: append captions anyhow
with local_session() as session: with local_session() as session:
shout = session.query(Shout).\ shout = session.query(Shout).\
options([ options([
@ -65,7 +65,7 @@ async def get_shout_by_slug(_, info, slug):
if not shout: if not shout:
print(f"[resolvers.zine] error: shout with slug {slug} not exist") print(f"[resolvers.zine] error: shout with slug {slug} not exist")
return {} #TODO return error field return {"error" : "shout not found"}
return shout return shout

View File

@ -189,9 +189,6 @@ type Mutation {
unfollow(what: FollowingEntity!, slug: String!): Result! unfollow(what: FollowingEntity!, slug: String!): Result!
# TODO: transform reaction with body to shout # TODO: transform reaction with body to shout
# NOTE: so-named 'collections' are tuned feeds
# TODO: Feed entity and CRUM: createFeed updateFeed deleteFeed mergeFeeds
} }
################################### Query ################################### Query
@ -229,7 +226,7 @@ type Query {
shoutsByCommunities(slugs: [String]!, page: Int!, size: Int!): [Shout]! shoutsByCommunities(slugs: [String]!, page: Int!, size: Int!): [Shout]!
myCandidates(page: Int!, size: Int!): [Shout]! # test myCandidates(page: Int!, size: Int!): [Shout]! # test
topViewed(page: Int!, size: Int!): [Shout]! 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]! topMonth(page: Int!, size: Int!): [Shout]!
topOverall(page: Int!, size: Int!): [Shout]! topOverall(page: Int!, size: Int!): [Shout]!
recentPublished(page: Int!, size: Int!): [Shout]! # homepage recentPublished(page: Int!, size: Int!): [Shout]! # homepage

View File

@ -4,7 +4,8 @@ from settings import PORT
import sys import sys
if __name__ == '__main__': if __name__ == '__main__':
x = sys.argv[1] or "" x = ''
if len(sys.argv) > 1: x = sys.argv[1]
if x == "dev": if x == "dev":
print("DEV MODE") print("DEV MODE")
headers = [ headers = [

View File

@ -12,7 +12,6 @@ class UserStorage:
self = UserStorage self = UserStorage
users = session.query(User).\ users = session.query(User).\
options(selectinload(User.roles), selectinload(User.ratings)).all() options(selectinload(User.roles), selectinload(User.ratings)).all()
# TODO: add shouts and reactions counters
self.users = dict([(user.id, user) for user in users]) self.users = dict([(user.id, user) for user in users])
print('[service.auth] %d users' % len(self.users)) print('[service.auth] %d users' % len(self.users))

View File

@ -48,7 +48,6 @@ class ReactedStorage:
self.this_day_reactions[shout] = reaction self.this_day_reactions[shout] = reaction
print('[service.reacted] watching %d shouts' % len(reactions)) print('[service.reacted] watching %d shouts' % len(reactions))
# TODO: add reactions ?
@staticmethod @staticmethod
async def get_shout(shout_slug): async def get_shout(shout_slug):

View File

@ -17,7 +17,6 @@ class ViewedByDay(Base):
class ViewedStorage: class ViewedStorage:
viewed = { viewed = {
'shouts': {}, 'shouts': {},
# TODO: ? 'reactions': {},
'topics': {} # TODO: get sum views for all shouts in topic 'topics': {} # TODO: get sum views for all shouts in topic
} }
this_day_views = {} this_day_views = {}
@ -43,7 +42,6 @@ class ViewedStorage:
self.this_day_views[shout] = view self.this_day_views[shout] = view
print('[service.viewed] watching %d shouts' % len(views)) print('[service.viewed] watching %d shouts' % len(views))
# TODO: add reactions ?
@staticmethod @staticmethod
async def get_shout(shout_slug): async def get_shout(shout_slug):

View File

@ -20,7 +20,8 @@ class ShoutAuthorStorage:
self.authors_by_shout[shout].append(user) self.authors_by_shout[shout].append(user)
else: else:
self.authors_by_shout[shout] = [user] 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 @staticmethod
async def get_authors(shout): async def get_authors(shout):