import sqlite3 from datetime import timedelta from goodnews import auth from goodnews.db import connect, init_db def _db(): c = connect(":memory:") init_db(c) # an article to save/history against later flows c.execute("INSERT INTO sources (id,name,feed_url,trust_score) VALUES (1,'S','http://s/f',5)") c.execute("INSERT INTO articles (id,source_id,canonical_url,title,url_hash) " "VALUES (1,1,'http://s/1','t1','h1')") c.commit() return c def test_normalize_email(): assert auth.normalize_email(" Foo@Bar.COM ") == "foo@bar.com" def test_find_or_create_links_by_email_and_dedupes_identity(): c = _db() uid = auth.find_or_create_user(c, "a@b.com", "email", "a@b.com") # same identity again → same user, no duplicate assert auth.find_or_create_user(c, "a@b.com", "email", "a@b.com") == uid # a different provider with the SAME verified email links to the same user uid2 = auth.find_or_create_user(c, "A@B.com", "google", "google-sub-123", display_name="A") assert uid2 == uid assert c.execute("SELECT COUNT(*) FROM users").fetchone()[0] == 1 assert c.execute("SELECT COUNT(*) FROM identities WHERE user_id=?", (uid,)).fetchone()[0] == 2 assert auth.get_user(c, uid)["display_name"] == "A" def test_returning_identity_refreshes_avatar(): c = _db() uid = auth.find_or_create_user(c, "a@b.com", "google", "gsub", display_name="A", avatar_url="http://pic/1") assert auth.get_user(c, uid)["avatar_url"] == "http://pic/1" # a repeat sign-in with the SAME identity must still refresh the picture assert auth.find_or_create_user(c, "a@b.com", "google", "gsub", avatar_url="http://pic/2") == uid assert auth.get_user(c, uid)["avatar_url"] == "http://pic/2" def test_magic_link_token_single_use(): c = _db() raw = auth.create_login_token(c, "a@b.com") assert auth.consume_login_token(c, raw) == "a@b.com" # first use works assert auth.consume_login_token(c, raw) is None # reuse rejected assert auth.consume_login_token(c, "nonsense") is None # unknown rejected def test_magic_link_token_expiry(): c = _db() raw = auth.create_login_token(c, "a@b.com") # backdate expiry into the past c.execute("UPDATE login_tokens SET expires_at = ?", (auth._iso(auth._now() - timedelta(minutes=1)),)) assert auth.consume_login_token(c, raw) is None def test_session_lifecycle(): c = _db() uid = auth.find_or_create_user(c, "a@b.com", "email", "a@b.com") tok = auth.create_session(c, uid, user_agent="pytest") user = auth.resolve_session(c, tok) assert user and user["id"] == uid and user["email"] == "a@b.com" assert auth.resolve_session(c, None) is None assert auth.resolve_session(c, "bogus") is None auth.revoke_session(c, tok) assert auth.resolve_session(c, tok) is None def test_session_expiry(): c = _db() uid = auth.find_or_create_user(c, "a@b.com", "email", "a@b.com") tok = auth.create_session(c, uid) c.execute("UPDATE sessions SET expires_at = ?", (auth._iso(auth._now() - timedelta(seconds=1)),)) assert auth.resolve_session(c, tok) is None