Skip to content
This repository was archived by the owner on Oct 7, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 88 additions & 23 deletions mapadroid/data_manager/modules/device.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import re
from typing import Optional
from typing import List, Optional
from .resource import Resource
from mapadroid.data_manager.modules.pogoauth import PogoAuth
from mapadroid.utils.logging import get_logger, LoggerEnums, get_origin_logger


logger = get_logger(LoggerEnums.data_manager)
pogoauth_fields = {
'ggl_login': 'google',
'ptc_login': 'ptc'
}


class Device(Resource):
Expand All @@ -15,7 +20,7 @@ class Device(Resource):
translations = {
'origin': 'name',
'pool': 'pool_id',
'walker': 'walker_id'
'walker': 'walker_id',
}
configuration = {
"fields": {
Expand Down Expand Up @@ -60,7 +65,7 @@ class Device(Resource):
"expected": str
}
},
"account_id": {
"ggl_login": {
"settings": {
"type": "emailselect_google",
"require": False,
Expand All @@ -72,6 +77,18 @@ class Device(Resource):
"uri_source": "api_pogoauth"
}
},
"ptc_login": {
"settings": {
"type": "ptcselector",
"require": False,
"empty": None,
"description": "PTC accounts assigned to the device",
"expected": list,
"uri": True,
"data_source": "pogoauth",
"uri_source": "api_pogoauth"
}
},
"interface_type": {
"settings": {
"type": "option",
Expand Down Expand Up @@ -300,15 +317,6 @@ class Device(Resource):
"expected": str
}
},
"ptc_login": {
"settings": {
"type": "text",
"require": False,
"description": "PTC User/Password (Format username,password). Use | to set more the one account "
"(username,password|username,password)",
"expected": str
}
},
"clear_game_data": {
"settings": {
"type": "option",
Expand Down Expand Up @@ -381,7 +389,9 @@ def flush_level(self) -> None:

def validate_custom(self) -> Optional[dict]:
data = self.get_resource(backend=True)
issues = {}
issues = {
'invalid': []
}
bad_macs = []
mac_fields = ['mac_address', 'wifi_mac_address']
for field in mac_fields:
Expand All @@ -392,20 +402,75 @@ def validate_custom(self) -> Optional[dict]:
if not re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", data[field].lower()):
bad_macs.append((field, 'Invalid MAC address'))
if bad_macs:
issues['issues'] = bad_macs
if 'account_id' in self._data['fields'] and self._data['fields']['account_id'] is not None:
sql = "SELECT COUNT(*)\n" \
"FROM `settings_device`\n" \
"WHERE `account_id` = %s AND `device_id` != %s"
if self._dbc.autofetch_value(sql, (self._data['fields']['account_id'], self.identifier)) > 0:
if 'invalid' not in issues:
issues['invalid'] = []
issues['invalid'].append(('account_id', 'Account already in use'))
if issues:
issues['invalid'] += bad_macs

if self['ggl_login'] is not None:
if self['ggl_login'] not in PogoAuth.get_avail_accounts(self._data_manager,
auth_type='google',
device_id=self.identifier):
issues['invalid'].append(('ggl_login', 'Invalid Google Account specified'))
if self['ptc_login'] is not None:
invalid_ptc = []
valid_auth = PogoAuth.get_avail_accounts(self._data_manager, 'ptc', device_id=self.identifier)
for ptc in self['ptc_login']:
if int(ptc) not in valid_auth:
invalid_ptc.append(ptc)
if invalid_ptc:
msg = 'Invalid PogoAuth specified [%s]' % ','.join([str(x) for x in invalid_ptc])
issues['invalid'].append(('ptc_login', msg))
if any(issues['invalid']):
return issues

def _load(self) -> None:
super()._load()
self.state = 0
if self._data_manager.is_device_active(self.identifier):
self.state = 1
for field, lookup_val in pogoauth_fields.items():
search = {
'device_id': self.identifier,
'login_type': lookup_val
}
logins = self._data_manager.search('pogoauth', params=search)
if field == 'ptc_login':
self[field] = list(logins.keys())
else:
try:
self[field] = next(iter(logins))
except StopIteration:
self[field] = None

def save(self, force_insert: Optional[bool] = False, ignore_issues: Optional[List[str]] = []) -> int:
core_data = self.get_core()
for field in pogoauth_fields:
try:
del core_data[field]
except KeyError:
pass
super().save(core_data=core_data, force_insert=force_insert, ignore_issues=ignore_issues)
# Clear out old values
for field, lookup_val in pogoauth_fields.items():
search = {
'device_id': self.identifier,
'login_type': lookup_val
}
matched_auths = self._data_manager.search('pogoauth', params=search)
for auth_id, auth in matched_auths.items():
if field == 'ggl_login' and self[field] != auth_id:
auth['device_id'] = None
auth.save()
elif field == 'ptc_login' and auth_id not in self[field]:
auth['device_id'] = None
auth.save()
# Save new auth
if self['ggl_login'] is not None:
pogoauth: PogoAuth = self._data_manager.get_resource('pogoauth', self['ggl_login'])
if pogoauth['device_id'] != self.identifier:
pogoauth['device_id'] = self.identifier
pogoauth.save()
if self['ptc_login']:
for auth_id in self['ptc_login']:
pogoauth: PogoAuth = self._data_manager.get_resource('pogoauth', auth_id)
if pogoauth['device_id'] != self.identifier:
pogoauth['device_id'] = self.identifier
pogoauth.save()
103 changes: 56 additions & 47 deletions mapadroid/data_manager/modules/pogoauth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List, Optional, Tuple
from typing import Dict, List, Tuple
from .resource import Resource
from mapadroid.data_manager.dm_exceptions import UnknownIdentifier


class PogoAuth(Resource):
Expand Down Expand Up @@ -49,56 +50,64 @@ class PogoAuth(Resource):
}
}

@classmethod
def get_avail_accounts(cls, data_manager, auth_type, device_id: int = None) -> Dict[int, Resource]:
accounts: Dict[int, Resource] = {}
search = {
'login_type': auth_type
}
pogoauths = data_manager.search('pogoauth', params=search)
try:
identifier = int(device_id)
except (ValueError, TypeError, UnknownIdentifier):
identifier = None
# Find all unassigned accounts
for account_id, account in pogoauths.items():
if account['device_id'] is not None:
if identifier is not None and account['device_id'] != identifier:
continue
accounts[account_id] = account
return accounts

@classmethod
def get_avail_devices(cls, data_manager, auth_id: int = None) -> Dict[int, Resource]:
invalid_devices = []
avail_devices: Dict[int, Resource] = {}
device_id: int = None
pogoauths = data_manager.search('pogoauth')
try:
identifier = int(auth_id)
except (ValueError, TypeError, UnknownIdentifier):
pass
else:
try:
device_id = pogoauths[identifier]['device_id']
except KeyError:
# Auth isn't found. Either it doesnt exist or auth_type mismatch
return avail_devices
for pauth_id, pauth in pogoauths.items():
if pauth['device_id'] is not None and device_id is not None and pauth['device_id'] != device_id:
invalid_devices.append(pauth['device_id'])
invalid_devices = list(set(invalid_devices))
for dev_id, dev in data_manager.get_root_resource('device').items():
if dev_id in invalid_devices:
continue
avail_devices[dev_id] = dev
return avail_devices

def get_dependencies(self) -> List[Tuple[str, int]]:
sql = 'SELECT `device_id` FROM `settings_device` WHERE `account_id` = %s'
sql = 'SELECT `device_id` FROM `settings_pogoauth` WHERE `account_id` = %s AND `device_id` IS NOT NULL'
dependencies = self._dbc.autofetch_column(sql, args=(self.identifier,))
for ind, device_id in enumerate(dependencies[:]):
dependencies[ind] = ('device', device_id)
return dependencies

def _load(self) -> None:
super()._load()
sql = "SELECT `device_id`\n" \
"FROM `settings_device`\n" \
"WHERE `account_id` = %s"
self._data['fields']['device_id'] = self._dbc.autofetch_value(sql, args=(self.identifier))

def save(self, force_insert: Optional[bool] = False, ignore_issues: Optional[List[str]] = []) -> int:
self.presave_validation(ignore_issues=ignore_issues)
device_id = self._data['fields']['device_id']
core_data = {
'login_type': self._data['fields']['login_type'],
'username': self._data['fields']['username'],
'password': self._data['fields']['password'],
}
super().save(core_data=core_data, force_insert=force_insert, ignore_issues=ignore_issues)
if device_id is not None:
device = self._data_manager.get_resource('device', device_id)
device['account_id'] = self.identifier
device.save()
else:
devices = self._data_manager.search('device', params={'account_id': self.identifier})
if devices:
device = devices[next(iter(devices))]
device['account_id'] = None
device.save()
return self.identifier

def validate_custom(self):
issues = {}
# One google account per device (for now)
login_type = None
try:
login_type = self._data['fields']['login_type']
except KeyError:
return issues
if login_type == 'google' and \
('device_id' in self._data['fields'] and self._data['fields']['device_id']):
sql = "SELECT `account_id`\n"\
"FROM `settings_device`\n"\
"WHERE `device_id` = %s"
aligned = self._dbc.autofetch_column(sql, (self._data['fields']['device_id']))
if len(aligned) == 1 and any(aligned):
if aligned[0] != self.identifier:
issues['invalid'] = [('device_id', 'Device already has a Google login')]
return issues
issues = []
if 'device_id' in self and self['device_id'] is not None:
if self['device_id'] not in PogoAuth.get_avail_devices(self._data_manager, auth_id=self.identifier):
issues.append(("device_id", "PogoAuth not valid for this device"))
if issues:
return {
'issues': issues
}
30 changes: 18 additions & 12 deletions mapadroid/data_manager/modules/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,23 @@ def delete(self):
}
self._dbc.autoexec_delete(self.table, del_data)

def get_core(self, clear: bool = False):
if clear:
data = copy.copy(self.get_resource(backend=True))
else:
data = self.get_resource(backend=True)
try:
for field, field_value in data['settings'].items():
data[field] = field_value
for field in data['settings'].removal:
data[field] = None
del self._data['settings'][field]
data['settings'].removal = []
del data['settings']
except KeyError:
pass
return data

def get_dependencies(self):
return []

Expand Down Expand Up @@ -327,7 +344,6 @@ def _load_defaults(self):
try:
for field, default_value in self.configuration[section].items():
try:
default_value['settings']['require'] is True and default_value['settings']['empty']
defaults[field] = default_value['settings']['empty']
except KeyError:
continue
Expand Down Expand Up @@ -371,17 +387,7 @@ def presave_validation(self, ignore_issues=[]):
def save(self, core_data=None, force_insert=False, ignore_issues=[], **kwargs):
self.presave_validation(ignore_issues=ignore_issues)
if core_data is None:
data = self.get_resource(backend=True)
try:
for field, field_value in data['settings'].items():
data[field] = field_value
for field in data['settings'].removal:
data[field] = None
del self._data['settings'][field]
data['settings'].removal = []
del data['settings']
except KeyError:
pass
data = self.get_core(clear=True)
else:
data = core_data
if self.include_instance_id:
Expand Down
32 changes: 20 additions & 12 deletions mapadroid/madmin/api/autoconf/ftr_autoconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def autoconf_set_status(self, session_id: int):
}
device = None
if status == 1:
is_hopper = False
ac_issues = AutoConfIssueGenerator(self.dbc, self._data_manager, self._args, self.storage_obj)
if ac_issues.has_blockers():
return ac_issues.get_issues(), 406, {"headers": ac_issues.get_headers()}
Expand All @@ -86,22 +87,29 @@ def autoconf_set_status(self, session_id: int):
return hopper_response
else:
update['device_id'] = hopper_response[1]
device = self._data_manager.get_resource('device', update['device_id'])
try:
has_ptc = device['settings']['ptc_login']
except KeyError:
has_ptc = False
if not self._args.autoconfig_no_auth and (device['account_id'] is None and not has_ptc):
# Auto-assign a google account as one was not specified
is_hopper = True
search = {
'device_id': update['device_id']
}
has_auth = self._data_manager.search('pogoauth', params=search)
if not self._args.autoconfig_no_auth and (not has_auth):
device = self._data_manager.get_resource('device', update['device_id'])
try:
auth_type = device['settings']['logintype']
except KeyError:
auth_type = 'google'
# Find one that matches authtype
sql = "SELECT ag.`account_id`\n"\
"FROM `settings_pogoauth` ag\n"\
"LEFT JOIN `settings_device` sd ON sd.`account_id` = ag.`account_id`\n"\
"WHERE sd.`device_id` IS NULL AND ag.`instance_id` = %s AND ag.`login_type` = %s"
account_id = self.dbc.autofetch_value(sql, (self.dbc.instance_id, 'google'))
"WHERE ag.`device_id` IS NULL AND ag.`instance_id` = %s AND ag.`login_type` = %s"
account_id = self.dbc.autofetch_value(sql, (self.dbc.instance_id, auth_type))
if account_id is None:
return ('No configured emails', 400)
device['account_id'] = account_id
device.save()
auth = self._data_manager.get_resource('pogoauth', account_id)
auth['device_id'] = device.identifier
if is_hopper and auth_type != 'google':
auth['login_type'] = auth_type
auth.save()
where = {
'session_id': session_id,
'instance_id': self.dbc.instance_id
Expand Down
Loading