Skip to content

Commit e523332

Browse files
committed
Add blog posts, merge info into site
1 parent 8d7fd35 commit e523332

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+922
-232
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ https://github.com/sdispater/poetry
2020

2121
# running the writeups server
2222

23-
`poetry run uvicorn writeups_site.site:app`
23+
`poetry run uvicorn luhack_site.site:app`
2424

2525
# performing database migrations
2626

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Add Blog posts
2+
3+
Revision ID: 8fb79834c64d
4+
Revises: 38952f538172
5+
Create Date: 2019-04-29 01:28:40.440714
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlalchemy_utils
11+
from sqlalchemy_searchable import sync_trigger
12+
13+
# revision identifiers, used by Alembic.
14+
revision = "8fb79834c64d"
15+
down_revision = "38952f538172"
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
conn = op.get_bind()
23+
24+
op.create_table(
25+
"blogs",
26+
sa.Column("id", sa.Integer(), nullable=False),
27+
sa.Column("title", sa.Text(), nullable=False),
28+
sa.Column("slug", sa.Text(), nullable=False),
29+
sa.Column("tags", sa.ARRAY(sa.Text()), nullable=False),
30+
sa.Column("content", sa.Text(), nullable=False),
31+
sa.Column(
32+
"creation_date",
33+
sa.DateTime(),
34+
server_default=sa.text("now()"),
35+
nullable=False,
36+
),
37+
sa.Column(
38+
"edit_date", sa.DateTime(), server_default=sa.text("now()"), nullable=False
39+
),
40+
sa.Column(
41+
"search_vector",
42+
sqlalchemy_utils.types.ts_vector.TSVectorType(
43+
"title", "content", weights={"title": "A", "content": "B"}
44+
),
45+
nullable=True,
46+
),
47+
sa.PrimaryKeyConstraint("id"),
48+
sa.UniqueConstraint("slug"),
49+
sa.UniqueConstraint("title"),
50+
)
51+
op.create_index(
52+
"blogs_tags_array_idx",
53+
"blogs",
54+
["tags"],
55+
unique=False,
56+
postgresql_using="gin",
57+
)
58+
59+
sync_trigger(conn, "blogs", "search_vector", ["title", "content"])
60+
# ### end Alembic commands ###
61+
62+
63+
def downgrade():
64+
# ### commands auto generated by Alembic - please adjust! ###
65+
op.drop_index("blogs_tags_array_idx", table_name="blogs")
66+
op.drop_table("blogs")
67+
# ### end Alembic commands ###

alembic/versions/da14a852b606_add_creation_and_edit_dates_to_writeups.py

+19-6
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,34 @@
1111

1212

1313
# revision identifiers, used by Alembic.
14-
revision = 'da14a852b606'
15-
down_revision = '98b885be8d35'
14+
revision = "da14a852b606"
15+
down_revision = "98b885be8d35"
1616
branch_labels = None
1717
depends_on = None
1818

1919

2020
def upgrade():
2121
# ### commands auto generated by Alembic - please adjust! ###
22-
op.add_column('writeups', sa.Column('creation_date', sa.DateTime(), server_default=sa.text('now()'), nullable=False))
23-
op.add_column('writeups', sa.Column('edit_date', sa.DateTime(), server_default=sa.text('now()'), nullable=False))
22+
op.add_column(
23+
"writeups",
24+
sa.Column(
25+
"creation_date",
26+
sa.DateTime(),
27+
server_default=sa.text("now()"),
28+
nullable=False,
29+
),
30+
)
31+
op.add_column(
32+
"writeups",
33+
sa.Column(
34+
"edit_date", sa.DateTime(), server_default=sa.text("now()"), nullable=False
35+
),
36+
)
2437
# ### end Alembic commands ###
2538

2639

2740
def downgrade():
2841
# ### commands auto generated by Alembic - please adjust! ###
29-
op.drop_column('writeups', 'edit_date')
30-
op.drop_column('writeups', 'creation_date')
42+
op.drop_column("writeups", "edit_date")
43+
op.drop_column("writeups", "creation_date")
3144
# ### end Alembic commands ###

luhack_bot/cogs/writeups.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def tag_url(tag):
2929

3030
@staticmethod
3131
def writeup_url(slug):
32-
return constants.writeups_base_url / "writeup" / slug
32+
return constants.writeups_base_url / "view" / slug
3333

3434
async def get_writeup(self, title: str) -> Optional[Writeup]:
3535
return await Writeup.query.where(Writeup.title == title).gino.first()
@@ -120,13 +120,15 @@ async def delete(self, ctx, *, title: str):
120120
await writeup.delete()
121121
await ctx.send(f"RIP {writeup.title}")
122122

123-
@writeups.command()
123+
@writeups.command(aliases=["link"])
124124
async def token(self, ctx):
125125
"""Generate a token allowing you to create writeups & manage those you have authority to."""
126126

127-
is_admin = self.luhack_guild.get_member(
128-
ctx.author.id
129-
).guild_permissions.administrator
127+
member_in_luhack = self.luhack_guild.get_member(ctx.author.id)
128+
129+
is_disciple = discord.utils.get(member_in_luhack.roles, id=constants.disciple_role_id) is not None
130+
is_admin = member_in_luhack.guild_permissions.administrator or is_disciple
131+
130132
token = generate_writeup_edit_token(ctx.author.name, ctx.author.id, is_admin)
131133

132134
url = constants.writeups_base_url.with_query(token=token)

luhack_bot/constants.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
luhack_guild_id = 485103891298385923
44
potential_luhacker_role_id = 486250289691754496
55
verified_luhacker_role_id = 486249689050644480
6-
writeups_base_url = yarl.URL("https://scc-luhack.lancs.ac.uk")
6+
disciple_role_id = 506420426419732499
7+
writeups_base_url = yarl.URL("https://scc-luhack.lancs.ac.uk/writeups")

luhack_bot/db/models.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,39 @@ class Image(db.Model):
6262
id = db.Column(UUID(), primary_key=True, server_default=func.uuid_generate_v4())
6363

6464
author_id = db.Column(None, db.ForeignKey("users.discord_id", ondelete="CASCADE"), nullable=False)
65-
author = relationship(User, backref=backref("writeups", passive_deletes=True), lazy="joined")
65+
author = relationship(User, backref=backref("images", passive_deletes=True), lazy="joined")
6666

6767
filetype = db.Column(db.Text(), nullable=False)
6868
image = db.Column(db.LargeBinary(), nullable=False)
69+
70+
71+
class Blog(db.Model):
72+
__tablename__ = "blogs"
73+
74+
id = db.Column(db.Integer, primary_key=True)
75+
76+
title = db.Column(db.Text(), nullable=False, unique=True)
77+
slug = db.Column(db.Text(), nullable=False, unique=True)
78+
79+
tags = db.Column(ARRAY(db.Text()), nullable=False)
80+
content = db.Column(db.Text(), nullable=False)
81+
82+
creation_date = db.Column(db.DateTime, server_default=func.now(), nullable=False)
83+
edit_date = db.Column(db.DateTime, server_default=func.now(), server_onupdate=func.now(), nullable=False)
84+
85+
search_vector = db.Column(
86+
TSVectorType("title", "content", weights={"title": "A", "content": "B"})
87+
)
88+
89+
_tags_idx = db.Index("blogs_tags_array_idx", "tags", postgresql_using="gin")
90+
91+
@classmethod
92+
def create_auto(cls, *args, **kwargs):
93+
if "slug" not in kwargs:
94+
kwargs["slug"] = slug(kwargs["title"])
95+
return cls.create(*args, **kwargs)
96+
97+
def update_auto(self, *args, **kwargs):
98+
if "slug" not in kwargs:
99+
kwargs["slug"] = slug(kwargs["title"])
100+
return self.update(*args, **kwargs)

writeups_site/middleware.py luhack_site/authorization.py

+10
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,13 @@ async def authenticate(self, request: HTTPConnection):
3838
creds.append("admin")
3939

4040
return AuthCredentials(creds), User(username, user_id, is_admin)
41+
42+
43+
def can_edit(request, author_id=None):
44+
if not request.user.is_authenticated:
45+
return False
46+
47+
if author_id is None:
48+
return request.user.is_admin
49+
50+
return request.user.is_admin or author_id == request.user.discord_id

0 commit comments

Comments
 (0)