Skip to content
Snippets Groups Projects
Commit 1c37871b authored by Tulir Asokan's avatar Tulir Asokan :cat2:
Browse files

Fix logging in with cookies and remove user agent stuff

parent d713649d
No related branches found
No related tags found
No related merge requests found
"""Remove user agent from db
Revision ID: 97e9f7a3c070
Revises: c56c9a30b228
Create Date: 2020-05-11 23:40:17.319060
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '97e9f7a3c070'
down_revision = 'c56c9a30b228'
branch_labels = None
depends_on = None
def upgrade():
with op.batch_alter_table("user") as batch_op:
batch_op.drop_column('user_agent')
def downgrade():
with op.batch_alter_table("user") as batch_op:
batch_op.add_column(sa.Column('user_agent', sa.String(length=255), autoincrement=False, nullable=True))
......@@ -14,10 +14,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import random
import time
from http.cookies import SimpleCookie
from yarl import URL
import fbchat
......@@ -28,22 +26,6 @@ from .. import puppet as pu
from mautrix.bridge import custom_puppet as cpu
from . import command_handler, CommandEvent, SECTION_AUTH
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
" Chrome/74.0.3729.169 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0",
# "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like"
# " Gecko) Version/12.1.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0",
# "Mozilla/5.0 (Linux; Android 9; SM-G960F Build/PPR1.180610.011; wv) AppleWebKit/537.36
# (KHTML,"
# " like Gecko) Version/4.0 Chrome/74.0.3729.157 Mobile Safari/537.36",
]
@command_handler(needs_auth=False, management_only=True,
help_section=SECTION_AUTH, help_text="Log in to Facebook",
......@@ -59,8 +41,6 @@ async def login(evt: CommandEvent) -> None:
"action": "Login",
"room_id": evt.room_id,
}
if not evt.sender.user_agent:
evt.sender.user_agent = random.choice(USER_AGENTS)
await evt.reply("Logging in...")
try:
session = await fbchat.Session.login(evt.args[0], " ".join(evt.args[1:]),
......@@ -74,18 +54,6 @@ async def login(evt: CommandEvent) -> None:
evt.log.exception("Failed to log in")
@command_handler(needs_auth=False, management_only=False, help_section=SECTION_AUTH,
help_text="Change the user agent sent to Facebook", help_args="<_user agent_>")
async def set_ua(evt: CommandEvent) -> None:
if len(evt.args) < 0:
await evt.reply("Usage: `$cmdprefix+sp login <user agent>`")
return
evt.sender.user_agent = " ".join(evt.args)
evt.sender.save()
await evt.reply(f"Set user agent to `{evt.sender.user_agent}`. The change will be applied when"
" you log in again or on the next bridge restart.")
async def enter_2fa_code(evt: CommandEvent) -> None:
code = " ".join(evt.args)
future: asyncio.Future = evt.sender.command_status["future"]
......@@ -150,14 +118,11 @@ async def enter_login_cookies(evt: CommandEvent) -> None:
"the `cancel` command to cancel.")
return
if not evt.sender.user_agent:
evt.sender.user_agent = random.choice(USER_AGENTS)
cookie = SimpleCookie()
cookie["c_user"] = evt.sender.command_status["c_user"]
cookie["xs"] = evt.args[0]
try:
session = await fbchat.Session.from_cookies(cookie)
session = await fbchat.Session.from_cookies({
"c_user": evt.sender.command_status["c_user"],
"xs": evt.args[0],
})
except fbchat.FacebookError as e:
evt.sender.command_status = None
await evt.reply(f"Failed to log in: {e}")
......
......@@ -13,8 +13,7 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Optional, Iterable
from http.cookies import SimpleCookie
from typing import Optional, Iterable, Dict
from sqlalchemy import Column, String, PickleType
......@@ -26,9 +25,8 @@ class User(Base):
__tablename__ = "user"
mxid: UserID = Column(String(255), primary_key=True)
session: SimpleCookie = Column(PickleType, nullable=True)
session: Dict[str, str] = Column(PickleType, nullable=True)
fbid: str = Column(String(255), nullable=True)
user_agent: str = Column(String(255), nullable=True)
@classmethod
def all(cls) -> Iterable['User']:
......
......@@ -15,7 +15,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import (Any, Dict, Iterator, Optional, Iterable, Type, Callable, Awaitable,
Union, TYPE_CHECKING)
from http.cookies import SimpleCookie
import asyncio
import logging
......@@ -47,24 +46,22 @@ class User:
client: Optional[fbchat.Client]
listener: Optional[fbchat.Listener]
listen_task: Optional[asyncio.Task]
user_agent: str
command_status: Optional[Dict[str, Any]]
is_whitelisted: bool
is_admin: bool
permission_level: str
_is_logged_in: Optional[bool]
_session_data: Optional[SimpleCookie]
_session_data: Optional[Dict[str, str]]
_db_instance: Optional[DBUser]
_community_helper: CommunityHelper
_community_id: Optional[CommunityID]
def __init__(self, mxid: UserID, session: Optional[SimpleCookie] = None,
user_agent: Optional[str] = None, db_instance: Optional[DBUser] = None) -> None:
def __init__(self, mxid: UserID, session: Optional[Dict[str, str]] = None,
db_instance: Optional[DBUser] = None) -> None:
self.mxid = mxid
self.by_mxid[mxid] = self
self.user_agent = user_agent
self.command_status = None
self.is_whitelisted, self.is_admin, self.permission_level = config.get_permissions(mxid)
self._is_logged_in = None
......@@ -90,21 +87,18 @@ class User:
@property
def db_instance(self) -> DBUser:
if not self._db_instance:
self._db_instance = DBUser(mxid=self.mxid, session=self._session_data,
fbid=self.fbid, user_agent=self.user_agent)
self._db_instance = DBUser(mxid=self.mxid, session=self._session_data, fbid=self.fbid)
return self._db_instance
def save(self, _update_session_data: bool = True) -> None:
self.log.debug("Saving session")
if _update_session_data and self.session:
self._session_data = self.session.get_cookies()
self.db_instance.edit(session=self._session_data, fbid=self.fbid,
user_agent=self.user_agent)
self.db_instance.edit(session=self._session_data, fbid=self.fbid)
@classmethod
def from_db(cls, db_user: DBUser) -> 'User':
return User(mxid=db_user.mxid, session=db_user.session, user_agent=db_user.user_agent,
db_instance=db_user)
return User(mxid=db_user.mxid, session=db_user.session, db_instance=db_user)
@classmethod
def get_all(cls) -> Iterator['User']:
......
......@@ -14,7 +14,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Optional, Dict
from http.cookies import SimpleCookie
import logging
import random
import string
......@@ -113,23 +112,13 @@ class PublicBridgeWebsite:
async def login(self, request: web.Request) -> web.Response:
user = self.check_token(request)
try:
user_agent = request.headers["User-Agent"]
except KeyError:
raise web.HTTPBadRequest(body='{"error": "Missing User-Agent header"}',
headers=self._headers)
try:
data = await request.json()
except json.JSONDecodeError:
raise web.HTTPBadRequest(body='{"error": "Malformed JSON"}', headers=self._headers)
cookie = SimpleCookie()
cookie["c_user"] = data["c_user"]
cookie["xs"] = data["xs"]
user.user_agent = user_agent
user.save()
try:
session = await fbchat.Session.from_cookies(cookie)
session = await fbchat.Session.from_cookies(data)
except fbchat.FacebookError:
self.log.debug("Failed to log in", exc_info=True)
raise web.HTTPUnauthorized(body='{"error": "Facebook authorization failed"}',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment