Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

Commit

Permalink
finish emails
Browse files Browse the repository at this point in the history
  • Loading branch information
tnix100 committed Sep 9, 2024
1 parent aa7c986 commit 6c9d4c8
Show file tree
Hide file tree
Showing 11 changed files with 639 additions and 204 deletions.
5 changes: 4 additions & 1 deletion cloudlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def __init__(self):
#"Kicked": "E:020 | Kicked", -- deprecated
#"ChatFull": "E:023 | Chat full", -- deprecated
#"LoggedOut": "I:024 | Logged out", -- deprecated
"Deleted": "E:025 | Deleted"
"Deleted": "E:025 | Deleted",
"AccountLocked": "E:026 | Account Locked"
}
self.commands: dict[str, function] = {
# Core commands
Expand Down Expand Up @@ -337,6 +338,8 @@ def proxy_api_request(
self.send_statuscode("2FARequired", listener)
case "accountDeleted":
self.send_statuscode("Deleted", listener)
case "accountLocked":
self.send_statuscode("AccountLocked", listener)
case "accountBanned":
self.send_statuscode("Banned", listener)
case "tooManyRequests":
Expand Down
65 changes: 32 additions & 33 deletions database.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import redis
import os
import secrets
import time
from radix import Radix
from hashlib import sha256
from base64 import urlsafe_b64encode
Expand Down Expand Up @@ -64,9 +65,15 @@
# Create account sessions indexes
try: db.acc_sessions.create_index([("user", pymongo.ASCENDING)], name="user")
except: pass
try: db.acc_sessions.create_index([("ip", pymongo.ASCENDING)], name="ip")
except: pass
try: db.acc_sessions.create_index([("refreshed_at", pymongo.ASCENDING)], name="refreshed_at")
except: pass

# Create security log indexes
try: db.security_log.create_index([("user", pymongo.ASCENDING)], name="user")
except: pass

# Create data exports indexes
try: db.data_exports.create_index([("user", pymongo.ASCENDING)], name="user")
except: pass
Expand All @@ -75,18 +82,6 @@
try: db.relationships.create_index([("_id.from", pymongo.ASCENDING)], name="from")
except: pass

# Create netinfo indexes
try: db.netinfo.create_index([("last_refreshed", pymongo.ASCENDING)], name="last_refreshed")
except: pass

# Create netlog indexes
try: db.netlog.create_index([("_id.ip", pymongo.ASCENDING)], name="ip")
except: pass
try: db.netlog.create_index([("_id.user", pymongo.ASCENDING)], name="user")
except: pass
try: db.netlog.create_index([("last_used", pymongo.ASCENDING)], name="last_used")
except: pass

# Create posts indexes
try:
db.posts.create_index([
Expand Down Expand Up @@ -186,25 +181,6 @@


# Create default database items
for username in ["Server", "Deleted", "Meower", "Admin", "username"]:
try:
db.usersv0.insert_one({
"_id": username,
"lower_username": username.lower(),
"uuid": None,
"created": None,
"pfp_data": None,
"avatar": None,
"avatar_color": None,
"quote": None,
"pswd": None,
"flags": 1,
"permissions": None,
"ban": None,
"last_seen": None,
"delete_after": None
})
except pymongo.errors.DuplicateKeyError: pass
try:
db.config.insert_one({
"_id": "migration",
Expand Down Expand Up @@ -323,16 +299,39 @@ def get_total_pages(collection: str, query: dict, page_size: int = 25) -> int:
"mfa_recovery_code": user["mfa_recovery_code"][:10]
}})

# Delete system users from DB
log("[Migrator] Deleting system users from DB")
db.usersv0.delete_many({"_id": {"$in": ["Server", "Deleted", "Meower", "Admin", "username"]}})

# Emails
log("[Migrator] Adding email addresses")
db.usersv0.update_many({"email": {"$exists": False}}, {"$set": {
"email": "",
"normalized_email_hash": ""
}})

# New sessions
log("[Migrator] Adding new sessions")
for user in db.usersv0.find({"tokens": {"$exists": True}}, projection={"_id": 1, "tokens": 1}):
for user in db.usersv0.find({
"tokens": {"$exists": True},
"last_seen": {"$ne": None, "$gt": int(time.time())-(86400*21)},
}, projection={"_id": 1, "tokens": 1}):
if user["tokens"]:
for token in user["tokens"]:
rdb.set(urlsafe_b64encode(sha256(token.encode()).digest()), user["_id"], ex=1209600) # 14 days
rdb.set(
urlsafe_b64encode(sha256(token.encode()).digest()),
user["_id"],
ex=86400*21 # 21 days
)
db.usersv0.update_many({}, {"$unset": {"tokens": ""}})
try: db.usersv0.drop_index("tokens")
except: pass

# No more netinfo and netlog
log("[Migrator] Removing netinfo and netlog")
db.netinfo.drop()
db.netlog.drop()

db.config.update_one({"_id": "migration"}, {"$set": {"database": CURRENT_DB_VERSION}})
log(f"[Migrator] Finished Migrating DB to version {CURRENT_DB_VERSION}")

Expand Down
4 changes: 3 additions & 1 deletion errors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class InvalidTokenSignature(Exception): pass

class SessionNotFound(Exception): pass
class AccSessionTokenExpired(Exception): pass

class AccSessionNotFound(Exception): pass

class EmailTicketExpired(Exception): pass
4 changes: 1 addition & 3 deletions rest_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,11 @@ async def internal_auth():


@app.before_request
async def check_ip():
async def get_ip():
if hasattr(request, "internal_ip") and request.internal_ip: # internal IP forwarding
request.ip = request.internal_ip
else:
request.ip = (request.headers.get("Cf-Connecting-Ip", request.remote_addr))
if request.path != "/status" and blocked_ips.search_best(request.ip):
return {"error": True, "type": "ipBlocked"}, 403


@app.before_request
Expand Down
46 changes: 21 additions & 25 deletions rest_api/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,21 +532,19 @@ async def get_user(username):
# Get netlogs
netlogs = [
{
"ip": netlog["_id"]["ip"],
"user": netlog["_id"]["user"],
"last_used": netlog["last_used"],
"ip": session._db["ip"],
"user": session.username,
"last_used": session._db["refreshed_at"],
}
for netlog in db.netlog.find(
{"_id.user": username}, sort=[("last_used", pymongo.DESCENDING)]
)
for session in AccSession.get_all(username)
]

# Get alts
alts = [
netlog["_id"]["user"]
for netlog in db.netlog.find(
{"_id.ip": {"$in": [netlog["ip"] for netlog in netlogs]}}
)
session["user"]
for session in db.acc_sessions.find({
"ip": {"$in": [netlog["ip"] for netlog in netlogs]}
})
]
if username in alts:
alts.remove(username)
Expand All @@ -557,7 +555,7 @@ async def get_user(username):
payload["recent_ips"] = [
{
"ip": netlog["ip"],
"netinfo": security.get_netinfo(netlog["ip"]),
"netinfo": security.get_ip_info(netlog["ip"]),
"last_used": netlog["last_used"],
"blocked": (
blocked_ips.search_best(netlog["ip"])
Expand Down Expand Up @@ -1096,9 +1094,6 @@ async def get_netinfo(ip):
if not security.has_permission(request.permissions, security.AdminPermissions.VIEW_IPS):
abort(403)

# Get netinfo
netinfo = security.get_netinfo(ip)

# Get netblocks
netblocks = []
for radix_node in blocked_ips.search_covering(ip):
Expand All @@ -1107,24 +1102,25 @@ async def get_netinfo(ip):
netblocks.append(db.netblock.find_one({"_id": radix_node.prefix}))

# Get netlogs
netlogs = [
{
"ip": netlog["_id"]["ip"],
"user": netlog["_id"]["user"],
"last_used": netlog["last_used"],
}
for netlog in db.netlog.find(
{"_id.ip": ip}, sort=[("last_used", pymongo.DESCENDING)]
)
]
hit_users = set()
netlogs = []
for session in db.acc_sessions.find({"ip": ip}, sort=[("refreshed_at", pymongo.DESCENDING)]):
if session["user"] in hit_users:
continue
netlogs.append({
"ip": session["ip"],
"user": session["user"],
"last_used": session["refreshed_at"]
})
hit_users.add(session["user"])

# Add log
security.add_audit_log("got_netinfo", request.user, request.ip, {"ip": ip})

# Return netinfo, netblocks, and netlogs
return {
"error": False,
"netinfo": netinfo,
"netinfo": security.get_ip_info(ip),
"netblocks": netblocks,
"netlogs": netlogs,
}, 200
Expand Down
2 changes: 2 additions & 0 deletions rest_api/v0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
from .home import home_bp
from .me import me_bp
from .emojis import emojis_bp
from .emails import emails_bp

v0 = Blueprint("v0", __name__)

v0.register_blueprint(auth_bp)
v0.register_blueprint(emails_bp)
v0.register_blueprint(me_bp)
v0.register_blueprint(home_bp)
v0.register_blueprint(inbox_bp)
Expand Down
Loading

0 comments on commit 6c9d4c8

Please sign in to comment.