idk WIP
This commit is contained in:
33
src/api/accounts.py
Normal file
33
src/api/accounts.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
|
from psycopg2._psycopg import connection
|
||||||
|
|
||||||
|
import db.accounts as db
|
||||||
|
import settings.settings as settings
|
||||||
|
from api.utils import get_password_hash
|
||||||
|
from db.internal import get_db_connection
|
||||||
|
|
||||||
|
accounts_router = APIRouter(prefix="/api/accounts", tags=["anon"])
|
||||||
|
|
||||||
|
|
||||||
|
@accounts_router.post("/add/user")
|
||||||
|
async def add_account(
|
||||||
|
platform: str,
|
||||||
|
login: str,
|
||||||
|
password: str,
|
||||||
|
metadata: dict,
|
||||||
|
conn: Annotated[connection, Depends(get_db_connection)]
|
||||||
|
):
|
||||||
|
if not settings.settings.allow_create_users:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Not allowed",
|
||||||
|
)
|
||||||
|
if db.check_account_existence(conn, platform, login, password):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT,
|
||||||
|
detail="Account already exists",
|
||||||
|
)
|
||||||
|
hashed_password = get_password_hash(password)
|
||||||
|
return db.create_user(conn, username, hashed_password, "user")
|
||||||
@ -3,6 +3,9 @@ from typing import Annotated
|
|||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import jwt
|
import jwt
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
from fastapi import Depends, HTTPException, status
|
from fastapi import Depends, HTTPException, status
|
||||||
from fastapi.security import OAuth2PasswordBearer
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
from jwt.exceptions import InvalidTokenError
|
from jwt.exceptions import InvalidTokenError
|
||||||
@ -17,6 +20,19 @@ from db.internal import get_db_connection
|
|||||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_str(string, key_hex):
|
||||||
|
key = bytes.fromhex(key_hex)
|
||||||
|
cipher = AES.new(key, AES.MODE_ECB) # Простейший режим (небезопасно для больших данных!)
|
||||||
|
encrypted_string = cipher.encrypt(pad(string.encode(), AES.block_size))
|
||||||
|
return encrypted_string
|
||||||
|
|
||||||
|
def decrypt_str(encrypted_string, key_hex):
|
||||||
|
key = bytes.fromhex(key_hex)
|
||||||
|
cipher = AES.new(key, AES.MODE_ECB)
|
||||||
|
string = unpad(cipher.decrypt(encrypted_string), AES.block_size)
|
||||||
|
return string.decode()
|
||||||
|
|
||||||
|
|
||||||
def verify_password(plain_password: str, hashed_password: str):
|
def verify_password(plain_password: str, hashed_password: str):
|
||||||
return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
|
return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
|
||||||
|
|
||||||
|
|||||||
128
src/db/accounts.py
Normal file
128
src/db/accounts.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import psycopg2.extras
|
||||||
|
from psycopg2._psycopg import connection
|
||||||
|
|
||||||
|
# account create and delete
|
||||||
|
|
||||||
|
def create_account(
|
||||||
|
conn: connection,
|
||||||
|
platform: str,
|
||||||
|
login: str,
|
||||||
|
password: int,
|
||||||
|
metadata: dict
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
insert into picrinth.accounts
|
||||||
|
(platform, login, password,
|
||||||
|
metadata, created_at)
|
||||||
|
values (%s, %s, %s, %s, now())
|
||||||
|
returning id
|
||||||
|
""",
|
||||||
|
(platform, login, password, json.dumps(metadata)),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return cur.rowcount > 0
|
||||||
|
|
||||||
|
|
||||||
|
def delete_account(
|
||||||
|
conn: connection,
|
||||||
|
account_id: str
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
delete from picrinth.accounts
|
||||||
|
where account_id = %s
|
||||||
|
""",
|
||||||
|
(account_id),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return cur.rowcount > 0
|
||||||
|
|
||||||
|
|
||||||
|
# account checks
|
||||||
|
|
||||||
|
def check_account_existence_by_id(
|
||||||
|
conn: connection,
|
||||||
|
account_id: str
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
select exists(
|
||||||
|
select 1
|
||||||
|
from picrinth.accounts
|
||||||
|
where account_id = %s
|
||||||
|
);
|
||||||
|
""",
|
||||||
|
(account_id),
|
||||||
|
)
|
||||||
|
return cur.fetchone()[0] # type: ignore
|
||||||
|
|
||||||
|
def check_account_existence(
|
||||||
|
conn: connection,
|
||||||
|
platform: str,
|
||||||
|
login: str,
|
||||||
|
password: str
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
select exists(
|
||||||
|
select 1
|
||||||
|
from picrinth.accounts
|
||||||
|
where platform = %s, login = %s, password = %s
|
||||||
|
);
|
||||||
|
""",
|
||||||
|
(platform, login, password),
|
||||||
|
)
|
||||||
|
return cur.fetchone()[0] # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
# account update
|
||||||
|
|
||||||
|
def update_account(
|
||||||
|
conn: connection,
|
||||||
|
account_id: str,
|
||||||
|
platform: str,
|
||||||
|
login: str,
|
||||||
|
password: int,
|
||||||
|
metadata: dict
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
update picrinth.accounts
|
||||||
|
SET platform = %s,
|
||||||
|
login = %s,
|
||||||
|
password = %s,
|
||||||
|
metadata = %s
|
||||||
|
where account_id = %s
|
||||||
|
""",
|
||||||
|
(platform, login, password, json.dumps(metadata), account_id),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return cur.rowcount > 0
|
||||||
|
|
||||||
|
|
||||||
|
# account receiving
|
||||||
|
|
||||||
|
def get_account(
|
||||||
|
conn: connection,
|
||||||
|
account_id: str
|
||||||
|
):
|
||||||
|
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
select username,
|
||||||
|
account_id, platform, login,
|
||||||
|
password, metadata, created_at
|
||||||
|
from picrinth.accounts
|
||||||
|
where account_id = %s
|
||||||
|
""",
|
||||||
|
(account_id),
|
||||||
|
)
|
||||||
|
return cur.fetchone()
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
from fastapi import HTTPException, status
|
||||||
from psycopg2._psycopg import connection
|
from psycopg2._psycopg import connection
|
||||||
|
|
||||||
import db.pictures as db
|
import db.pictures as db
|
||||||
@ -26,6 +27,12 @@ def generate_feed(
|
|||||||
pixiv()
|
pixiv()
|
||||||
case "gelbooru":
|
case "gelbooru":
|
||||||
gelbooru()
|
gelbooru()
|
||||||
|
case _:
|
||||||
|
return HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Platform is not supported",
|
||||||
|
)
|
||||||
|
|
||||||
# TODO: remove mock results
|
# TODO: remove mock results
|
||||||
pictures_ids = db.get_all_pictures_ids(conn)
|
pictures_ids = db.get_all_pictures_ids(conn)
|
||||||
return pictures_ids
|
return pictures_ids
|
||||||
|
|||||||
@ -73,8 +73,9 @@ create table picrinth.accounts (
|
|||||||
platform text not null,
|
platform text not null,
|
||||||
login text not null,
|
login text not null,
|
||||||
password text not null,
|
password text not null,
|
||||||
metadata jsonb null, -- meybe not needed
|
metadata jsonb null,
|
||||||
created_at timestamp with time zone default now(),
|
created_at timestamp with time zone default now(),
|
||||||
|
primary key (id),
|
||||||
constraint unique_account_per_platform unique (platform, login)
|
constraint unique_account_per_platform unique (platform, login)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ create table picrinth.group_accounts (
|
|||||||
groupname text not null,
|
groupname text not null,
|
||||||
account_id int not null,
|
account_id int not null,
|
||||||
created_at timestamp with time zone default now(),
|
created_at timestamp with time zone default now(),
|
||||||
constraint unique_group_accounts unique (account_id, groupname)
|
constraint unique_group_accounts unique (account_id, groupname),
|
||||||
foreign key (groupname) references picrinth.groups (groupname) on delete cascade on update cascade
|
foreign key (groupname) references picrinth.groups (groupname) on delete cascade on update cascade,
|
||||||
foreign key (account_id) references picrinth.accounts (id) on delete cascade on update cascade
|
foreign key (account_id) references picrinth.accounts (id) on delete cascade on update cascade
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user