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():
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")

View File

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

View File

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

View File

@ -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), '<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:
print('[extract] found %d tooltips' % len(matches))
return newbody
@ -54,7 +54,7 @@ cache = {}
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:]
i = 0
for match in matches:
@ -63,7 +63,7 @@ def reextract_images(body, oid):
name = oid + str(i)
link = public + '/upload/image-' + name + '.' + ext
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:
content = base64.b64decode(img + '==')
print(str(len(img)) + ' image bytes been written')
@ -72,7 +72,7 @@ def reextract_images(body, oid):
i += 1
else:
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
IMAGES = {

View File

@ -30,8 +30,7 @@ from .utils import (
__version__ = (2020, 1, 16)
# TODO:
# Support decoded entities with UNIFIABLE.
# TODO: Support decoded entities with UNIFIABLE.
class HTML2Text(html.parser.HTMLParser):
@ -503,7 +502,7 @@ class HTML2Text(html.parser.HTMLParser):
self.handle_emphasis(start, tag_style, parent_style)
if tag in ["kbd", "code", "tt"] and not self.pre:
self.o("`") # TODO: `` `this` ``
self.o("`") # `` `this` ``
self.code = not self.code
if tag == "abbr":
@ -681,7 +680,7 @@ class HTML2Text(html.parser.HTMLParser):
# Indent two spaces per list, except use three spaces for an
# unordered list inside an ordered list.
# 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
for list in self.list:
self.o(
@ -761,7 +760,6 @@ class HTML2Text(html.parser.HTMLParser):
self.out("\n[/code]")
self.p()
# TODO: Add docstring for these one letter functions
def pbr(self) -> None:
"Pretty print has a line break"
if self.p_p == 0:
@ -807,7 +805,7 @@ class HTML2Text(html.parser.HTMLParser):
return
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"):
# <pre>stuff...
data = "\n" + data

View File

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

View File

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

View File

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

View File

@ -8,4 +8,4 @@ class Notification(Base):
template: str = Column(String, nullable = False)
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.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')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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