Change how roles are represented

merge-requests/30/head
Bob Mottram 2021-05-16 16:10:39 +01:00
parent 2a3ad46c05
commit 65b0a6b728
7 changed files with 292 additions and 148 deletions

View File

@ -123,6 +123,7 @@ from blocking import removeGlobalBlock
from blocking import isBlockedHashtag from blocking import isBlockedHashtag
from blocking import isBlockedDomain from blocking import isBlockedDomain
from blocking import getDomainBlocklist from blocking import getDomainBlocklist
from roles import getActorRolesList
from roles import setRole from roles import setRole
from roles import clearModeratorStatus from roles import clearModeratorStatus
from roles import clearEditorStatus from roles import clearEditorStatus
@ -200,6 +201,8 @@ from shares import addShare
from shares import removeShare from shares import removeShare
from shares import expireShares from shares import expireShares
from categories import setHashtagCategory from categories import setHashtagCategory
from utils import getOccupationName
from utils import setOccupationName
from utils import loadTranslationsFromFile from utils import loadTranslationsFromFile
from utils import getLocalNetworkAddresses from utils import getLocalNetworkAddresses
from utils import decodedHost from utils import decodedHost
@ -4581,21 +4584,18 @@ class PubServer(BaseHTTPRequestHandler):
actorChanged = True actorChanged = True
# Other accounts (alsoKnownAs) # Other accounts (alsoKnownAs)
occupationName = "" occupationName = getOccupationName(actorJson)
if actorJson.get('hasOccupation'):
if actorJson['hasOccupation'].get('name'):
occupationName = actorJson['hasOccupation']['name']
if fields.get('occupationName'): if fields.get('occupationName'):
fields['occupationName'] = \ fields['occupationName'] = \
removeHtml(fields['occupationName']) removeHtml(fields['occupationName'])
if occupationName != \ if occupationName != \
fields['occupationName']: fields['occupationName']:
actorJson['hasOccupation']['name'] = \ setOccupationName(actorJson,
fields['occupationName'] fields['occupationName'])
actorChanged = True actorChanged = True
else: else:
if occupationName: if occupationName:
actorJson['hasOccupation']['name'] = '' setOccupationName(actorJson, '')
actorChanged = True actorChanged = True
# Other accounts (alsoKnownAs) # Other accounts (alsoKnownAs)
@ -7373,7 +7373,7 @@ class PubServer(BaseHTTPRequestHandler):
if not actorJson: if not actorJson:
return False return False
if actorJson.get('affiliation'): if actorJson.get('hasOccupation'):
if self._requestHTTP(): if self._requestHTTP():
getPerson = \ getPerson = \
personLookup(domain, path.replace('/roles', ''), personLookup(domain, path.replace('/roles', ''),
@ -7394,11 +7394,7 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.keyShortcuts.get(nickname): if self.server.keyShortcuts.get(nickname):
accessKeys = self.server.keyShortcuts[nickname] accessKeys = self.server.keyShortcuts[nickname]
rolesList = [] rolesList = getActorRolesList(actorJson)
if actorJson.get('affiliation'):
if isinstance(actorJson['affiliation']['roleName'],
list):
rolesList = actorJson['affiliation']['roleName']
city = self._getSpoofedCity(baseDir, nickname, domain) city = self._getSpoofedCity(baseDir, nickname, domain)
msg = \ msg = \
htmlProfile(self.server.rssIconAtTop, htmlProfile(self.server.rssIconAtTop,
@ -7435,12 +7431,7 @@ class PubServer(BaseHTTPRequestHandler):
'show roles') 'show roles')
else: else:
if self._fetchAuthenticated(): if self._fetchAuthenticated():
rolesList = [] rolesList = getActorRolesList(actorJson)
if actorJson.get('affiliation'):
if isinstance(actorJson['affiliation']['roleName'],
list):
rolesList = actorJson['affiliation']['roleName']
msg = json.dumps(rolesList, msg = json.dumps(rolesList,
ensure_ascii=False) ensure_ascii=False)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')

View File

@ -34,6 +34,8 @@ from posts import createModeration
from auth import storeBasicCredentials from auth import storeBasicCredentials
from auth import removePassword from auth import removePassword
from roles import setRole from roles import setRole
from roles import setRolesFromList
from roles import getActorRolesList
from media import processMetaData from media import processMetaData
from utils import getStatusNumber from utils import getStatusNumber
from utils import getFullDomain from utils import getFullDomain
@ -201,10 +203,12 @@ def getDefaultPersonContext() -> str:
'toot': 'http://joinmastodon.org/ns#', 'toot': 'http://joinmastodon.org/ns#',
'value': 'schema:value', 'value': 'schema:value',
'hasOccupation': 'schema:hasOccupation', 'hasOccupation': 'schema:hasOccupation',
'affiliation': 'schema:affiliation',
'Occupation': 'schema:Occupation', 'Occupation': 'schema:Occupation',
'OrganizationRole': 'schema:OrganizationRole', 'occupationalCategory': 'schema:occupationalCategory',
'WebSite': 'schema:Project' 'Role': 'schema:Role',
'WebSite': 'schema:Project',
'CategoryCode': 'schema:CategoryCode',
'CategoryCodeSet': 'schema:CategoryCodeSet'
} }
@ -280,20 +284,13 @@ def _createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
'following': personId + '/following', 'following': personId + '/following',
'tts': personId + '/speaker', 'tts': personId + '/speaker',
'shares': personId + '/shares', 'shares': personId + '/shares',
'hasOccupation': { 'hasOccupation': [
'@type': 'Occupation', {
'name': "", '@type': 'Occupation',
'skills': [] 'name': "",
}, 'skills': []
"affiliation": { }
"@type": "OrganizationRole", ],
"roleName": [],
"affiliation": {
"@type": "WebSite",
"url": httpPrefix + '://' + domain
},
"startDate": published
},
'availability': None, 'availability': None,
'icon': { 'icon': {
'mediaType': 'image/png', 'mediaType': 'image/png',
@ -587,16 +584,13 @@ def personUpgradeActor(baseDir: str, personJson: {},
# if the older skills format is being used then switch # if the older skills format is being used then switch
# to the new one # to the new one
if not personJson.get('hasOccupation'): if not personJson.get('hasOccupation'):
personJson['hasOccupation'] = { personJson['hasOccupation'] = [
'@type': 'Occupation', {
'name': occupationName, '@type': 'Occupation',
'skills': [] 'name': occupationName,
} 'skills': []
updateActor = True }
]
if isinstance(personJson['hasOccupation']['skills'], str):
skillsList = personJson['hasOccupation']['skills'].split(', ')
personJson['hasOccupation']['skills'] = skillsList
updateActor = True updateActor = True
# remove the old skills format # remove the old skills format
@ -606,36 +600,29 @@ def personUpgradeActor(baseDir: str, personJson: {},
# if the older roles format is being used then switch # if the older roles format is being used then switch
# to the new one # to the new one
if not personJson.get('affiliation'): if personJson.get('affiliation'):
rolesList = [] del personJson['affiliation']
adminName = getConfigParam(baseDir, 'admin')
if personJson['id'].endswith('/users/' + adminName):
rolesList = ["admin", "moderator", "editor"]
statusNumber, published = getStatusNumber()
personJson['affiliation'] = {
"@type": "OrganizationRole",
"roleName": rolesList,
"affiliation": {
"@type": "WebSite",
"url": personJson['id'].split('/users/')[0]
},
"startDate": published
}
updateActor = True updateActor = True
if isinstance(personJson['affiliation']['roleName'], str): if not isinstance(personJson['hasOccupation'], list):
rolesList = personJson['affiliation']['roleName'].split(', ') personJson['hasOccupation'] = [
personJson['affiliation']['roleName'] = rolesList {
'@type': 'Occupation',
'name': occupationName,
'skills': []
}
]
updateActor = True updateActor = True
# if no roles are defined then ensure that the admin # if no roles are defined then ensure that the admin
# roles are configured # roles are configured
if not personJson['affiliation']['roleName']: rolesList = getActorRolesList(personJson)
if not rolesList:
adminName = getConfigParam(baseDir, 'admin') adminName = getConfigParam(baseDir, 'admin')
if personJson['id'].endswith('/users/' + adminName): if personJson['id'].endswith('/users/' + adminName):
personJson['affiliation']['roleName'] = \ rolesList = ["admin", "moderator", "editor"]
["admin", "moderator", "editor"] setRolesFromList(personJson, rolesList)
updateActor = True updateActor = True
# remove the old roles format # remove the old roles format
if personJson.get('roles'): if personJson.get('roles'):

124
roles.py
View File

@ -9,6 +9,7 @@ __status__ = "Production"
import os import os
from utils import loadJson from utils import loadJson
from utils import saveJson from utils import saveJson
from utils import getStatusNumber
def _clearRoleStatus(baseDir: str, role: str) -> None: def _clearRoleStatus(baseDir: str, role: str) -> None:
@ -30,12 +31,10 @@ def _clearRoleStatus(baseDir: str, role: str) -> None:
actorJson = loadJson(filename) actorJson = loadJson(filename)
if not actorJson: if not actorJson:
continue continue
if not actorJson.get('affiliation'): rolesList = getActorRolesList(actorJson)
continue
rolesList = \
getRolesFromList(actorJson['affiliation']['roleName'])
if role in rolesList: if role in rolesList:
rolesList.remove(role) rolesList.remove(role)
setRolesFromList(actorJson, rolesList)
saveJson(actorJson, filename) saveJson(actorJson, filename)
@ -65,7 +64,8 @@ def clearModeratorStatus(baseDir: str) -> None:
def _addRole(baseDir: str, nickname: str, domain: str, def _addRole(baseDir: str, nickname: str, domain: str,
roleFilename: str) -> None: roleFilename: str) -> None:
"""Adds a role nickname to the file """Adds a role nickname to the file.
This is a file containing the nicknames of accounts having this role
""" """
if ':' in domain: if ':' in domain:
domain = domain.split(':')[0] domain = domain.split(':')[0]
@ -94,7 +94,8 @@ def _addRole(baseDir: str, nickname: str, domain: str,
def _removeRole(baseDir: str, nickname: str, roleFilename: str) -> None: def _removeRole(baseDir: str, nickname: str, roleFilename: str) -> None:
"""Removes a role nickname from the file """Removes a role nickname from the file.
This is a file containing the nicknames of accounts having this role
""" """
roleFile = baseDir + '/accounts/' + roleFilename roleFile = baseDir + '/accounts/' + roleFilename
if not os.path.isfile(roleFile): if not os.path.isfile(roleFile):
@ -108,24 +109,99 @@ def _removeRole(baseDir: str, nickname: str, roleFilename: str) -> None:
f.write(roleNickname + '\n') f.write(roleNickname + '\n')
def _setActorRole(actorJson: {}, roleName: str) -> bool:
"""Sets a role for an actor
"""
if not actorJson.get('hasOccupation'):
return False
if not isinstance(actorJson['hasOccupation'], list):
return False
category = None
if 'admin' in roleName:
category = '15-1299.01'
elif 'moderator' in roleName:
category = '11-9199.02'
elif 'editor' in roleName:
category = '27-3041.00'
elif 'counselor' in roleName:
category = '23-1022.00'
if not category:
return False
for index in range(len(actorJson['hasOccupation'])):
occupationItem = actorJson['hasOccupation'][index]
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] != 'Role':
continue
if occupationItem['hasOccupation']['name'] == roleName:
return True
statusNumber, published = getStatusNumber()
newRole = {
"@type": "Role",
"hasOccupation": {
"@type": "Occupation",
"name": roleName,
"occupationalCategory": {
"@type": "CategoryCode",
"inCodeSet": {
"@type": "CategoryCodeSet",
"name": "O*Net-SOC",
"dateModified": "2019",
"url": "https://www.onetonline.org/"
},
"codeValue": category,
"url": "https://www.onetonline.org/link/summary/" + category
}
},
"startDate": published
}
actorJson['hasOccupation'].append(newRole)
return True
def setRolesFromList(actorJson: {}, rolesList: []) -> None: def setRolesFromList(actorJson: {}, rolesList: []) -> None:
"""Sets roles from a list """Sets roles from a list
""" """
if actorJson.get('affiliation'): # clear Roles from the occupation list
actorJson['affiliation']['roleName'] = rolesList.copy() emptyRolesList = []
for occupationItem in actorJson['hasOccupation']:
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] == 'Role':
continue
emptyRolesList.append(occupationItem)
actorJson['hasOccupation'] = emptyRolesList
# create the new list
for roleName in rolesList:
_setActorRole(actorJson, roleName)
def getRolesFromList(rolesList: []) -> []: def getActorRolesList(actorJson: {}) -> []:
"""Returns a list of roles from a list """Gets a list of role names from an actor
""" """
if isinstance(rolesList, list): if not actorJson.get('hasOccupation'):
rolesList2 = rolesList return []
else: if not isinstance(actorJson['hasOccupation'], list):
rolesList2 = rolesList.split(',') return []
rolesResult = [] rolesList = []
for roleName in rolesList2: for occupationItem in actorJson['hasOccupation']:
rolesResult.append(roleName.strip().lower()) if not isinstance(occupationItem, dict):
return rolesResult continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] != 'Role':
continue
roleName = occupationItem['hasOccupation']['name']
if roleName not in rolesList:
rolesList.append(roleName)
return rolesList
def setRole(baseDir: str, nickname: str, domain: str, def setRole(baseDir: str, nickname: str, domain: str,
@ -149,10 +225,9 @@ def setRole(baseDir: str, nickname: str, domain: str,
actorJson = loadJson(actorFilename) actorJson = loadJson(actorFilename)
if actorJson: if actorJson:
if not actorJson.get('affiliation'): if not actorJson.get('hasOccupation'):
return False return False
rolesList = \ rolesList = getActorRolesList(actorJson)
getRolesFromList(actorJson['affiliation']['roleName'])
actorChanged = False actorChanged = False
if role: if role:
# add the role # add the role
@ -174,3 +249,10 @@ def setRole(baseDir: str, nickname: str, domain: str,
if actorChanged: if actorChanged:
saveJson(actorJson, actorFilename) saveJson(actorJson, actorFilename)
return True return True
def actorHasRole(actorJson: {}, roleName: str) -> bool:
"""Returns true if the given actor has the given role
"""
rolesList = getActorRolesList(actorJson)
return roleName in rolesList

View File

@ -15,16 +15,18 @@ from utils import getFullDomain
from utils import getNicknameFromActor from utils import getNicknameFromActor
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import loadJson from utils import loadJson
from utils import getOccupationSkills
from utils import setOccupationSkillsList
def setSkillsFromDict(actorJson: {}, skillsDict: {}) -> []: def setSkillsFromDict(actorJson: {}, skillsDict: {}) -> []:
"""Converts a dict containing skills to a string """Converts a dict containing skills to a list
Returns the string version of the dictionary Returns the string version of the dictionary
""" """
skillsList = [] skillsList = []
for name, value in skillsDict.items(): for name, value in skillsDict.items():
skillsList.append(name + ':' + str(value)) skillsList.append(name + ':' + str(value))
actorJson['hasOccupation']['skills'] = skillsList setOccupationSkillsList(actorJson, skillsList)
return skillsList return skillsList
@ -47,21 +49,11 @@ def getSkillsFromList(skillsList: []) -> {}:
return skillsDict return skillsDict
def actorHasSkill(actorJson: {}, skillName: str) -> bool:
"""Returns true if the actor has the given skill
"""
skillsDict = \
getSkillsFromList(actorJson['hasOccupation']['skills'])
if not skillsDict:
return False
return skillsDict.get(skillName.lower())
def actorSkillValue(actorJson: {}, skillName: str) -> int: def actorSkillValue(actorJson: {}, skillName: str) -> int:
"""Returns The skill level from an actor """Returns The skill level from an actor
""" """
skillsDict = \ ocSkillsList = getOccupationSkills(actorJson)
getSkillsFromList(actorJson['hasOccupation']['skills']) skillsDict = getSkillsFromList(ocSkillsList)
if not skillsDict: if not skillsDict:
return 0 return 0
skillName = skillName.lower() skillName = skillName.lower()
@ -74,13 +66,8 @@ def noOfActorSkills(actorJson: {}) -> int:
"""Returns the number of skills that an actor has """Returns the number of skills that an actor has
""" """
if actorJson.get('hasOccupation'): if actorJson.get('hasOccupation'):
skillsStr = actorJson['hasOccupation']['skills'] skillsList = getOccupationSkills(actorJson)
if isinstance(skillsStr, list): return len(skillsList)
skillsList = skillsStr
else:
skillsList = skillsStr.split(',')
if skillsList:
return len(skillsList)
return 0 return 0
@ -95,13 +82,15 @@ def setActorSkillLevel(actorJson: {},
if not actorJson: if not actorJson:
return True return True
if not actorJson.get('hasOccupation'): if not actorJson.get('hasOccupation'):
actorJson['hasOccupation'] = { actorJson['hasOccupation'] = [
'@type': 'Occupation', {
'name': '', '@type': 'Occupation',
'skills': '' 'name': '',
} 'skills': []
skillsDict = \ }
getSkillsFromList(actorJson['hasOccupation']['skills']) ]
ocSkillsList = getOccupationSkills(actorJson)
skillsDict = getSkillsFromList(ocSkillsList)
if skillLevelPercent > 0: if skillLevelPercent > 0:
skillsDict[skill] = skillLevelPercent skillsDict[skill] = skillLevelPercent
else: else:
@ -138,7 +127,8 @@ def getSkills(baseDir: str, nickname: str, domain: str) -> []:
if actorJson: if actorJson:
if not actorJson.get('hasOccupation'): if not actorJson.get('hasOccupation'):
return None return None
return getSkillsFromList(actorJson['hasOccupation']['skills']) ocSkillsList = getOccupationSkills(actorJson)
return getSkillsFromList(ocSkillsList)
return None return None
@ -258,3 +248,13 @@ def sendSkillViaServer(baseDir: str, session, nickname: str, password: str,
print('DEBUG: c2s POST skill success') print('DEBUG: c2s POST skill success')
return newSkillJson return newSkillJson
def actorHasSkill(actorJson: {}, skillName: str) -> bool:
"""Returns true if the given actor has the given skill
"""
ocSkillsList = getOccupationSkills(actorJson)
for skillStr in ocSkillsList:
if skillName + ':' in skillStr:
return True
return False

View File

@ -67,11 +67,12 @@ from person import setDisplayNickname
from person import setBio from person import setBio
# from person import generateRSAKey # from person import generateRSAKey
from skills import setSkillLevel from skills import setSkillLevel
from skills import actorSkillValue
from skills import setSkillsFromDict from skills import setSkillsFromDict
from skills import getSkillsFromList from skills import actorHasSkill
from roles import setRolesFromList from roles import setRolesFromList
from roles import getRolesFromList
from roles import setRole from roles import setRole
from roles import actorHasRole
from auth import constantTimeStringCheck from auth import constantTimeStringCheck
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
from auth import authorizeBasic from auth import authorizeBasic
@ -3661,44 +3662,42 @@ def testSpoofGeolocation() -> None:
def testSkills() -> None: def testSkills() -> None:
print('testSkills') print('testSkills')
actorJson = { actorJson = {
'hasOccupation': { 'hasOccupation': [
'@type': 'Occupation', {
'name': "", '@type': 'Occupation',
'skills': [] 'name': "Sysop",
} 'skills': []
}
]
} }
skillsDict = { skillsDict = {
'bakery': 40, 'bakery': 40,
'gardening': 70 'gardening': 70
} }
setSkillsFromDict(actorJson, skillsDict) setSkillsFromDict(actorJson, skillsDict)
assert actorJson['hasOccupation']['skills'] assert actorHasSkill(actorJson, 'bakery')
skillsDict = getSkillsFromList(actorJson['hasOccupation']['skills']) assert actorHasSkill(actorJson, 'gardening')
assert skillsDict.get('bakery') assert actorSkillValue(actorJson, 'bakery') == 40
assert skillsDict.get('gardening') assert actorSkillValue(actorJson, 'gardening') == 70
assert skillsDict['bakery'] == 40
assert skillsDict['gardening'] == 70
def testRoles() -> None: def testRoles() -> None:
print('testRoles') print('testRoles')
actorJson = { actorJson = {
'affiliation': { 'hasOccupation': [
"@type": "OrganizationRole", {
"roleName": [], '@type': 'Occupation',
"affiliation": { 'name': "Sysop",
"@type": "WebSite", 'skills': []
"url": "https://testinstance.org" }
}, ]
"startDate": "date goes here"
}
} }
testRolesList = ["admin", "moderator"] testRolesList = ["admin", "moderator"]
setRolesFromList(actorJson, testRolesList) setRolesFromList(actorJson, testRolesList)
assert actorJson['affiliation']['roleName'] assert actorHasRole(actorJson, "admin")
rolesList = getRolesFromList(actorJson['affiliation']['roleName']) assert actorHasRole(actorJson, "moderator")
assert 'admin' in rolesList assert not actorHasRole(actorJson, "editor")
assert 'moderator' in rolesList assert not actorHasRole(actorJson, "counselor")
def runAllTests(): def runAllTests():

View File

@ -2279,3 +2279,89 @@ def dmAllowedFromDomain(baseDir: str,
if sendingActorDomain + '\n' in open(dmAllowedInstancesFilename).read(): if sendingActorDomain + '\n' in open(dmAllowedInstancesFilename).read():
return True return True
return False return False
def getOccupationSkills(actorJson: {}) -> []:
"""Returns the list of skills for an actor
"""
if 'hasOccupation' not in actorJson:
return []
if not isinstance(actorJson['hasOccupation'], list):
return []
for occupationItem in actorJson['hasOccupation']:
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if not occupationItem['@type'] == 'Occupation':
continue
if not occupationItem.get('skills'):
continue
if isinstance(occupationItem['skills'], list):
return occupationItem['skills']
elif isinstance(occupationItem['skills'], str):
return [occupationItem['skills']]
break
return []
def getOccupationName(actorJson: {}) -> str:
"""Returns the occupation name an actor
"""
if not actorJson.get('hasOccupation'):
return ""
if not isinstance(actorJson['hasOccupation'], list):
return ""
for occupationItem in actorJson['hasOccupation']:
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] != 'Occupation':
continue
if not occupationItem.get('name'):
continue
if isinstance(occupationItem['name'], str):
return occupationItem['name']
break
return ""
def setOccupationName(actorJson: {}, name: str) -> bool:
"""Sets the occupation name of an actor
"""
if not actorJson.get('hasOccupation'):
return False
if not isinstance(actorJson['hasOccupation'], list):
return False
for index in range(len(actorJson['hasOccupation'])):
occupationItem = actorJson['hasOccupation'][index]
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] != 'Occupation':
continue
occupationItem['name'] = name
return True
return False
def setOccupationSkillsList(actorJson: {}, skillsList: []) -> bool:
"""Sets the occupation skills for an actor
"""
if 'hasOccupation' not in actorJson:
return False
if not isinstance(actorJson['hasOccupation'], list):
return False
for index in range(len(actorJson['hasOccupation'])):
occupationItem = actorJson['hasOccupation'][index]
if not isinstance(occupationItem, dict):
continue
if not occupationItem.get('@type'):
continue
if occupationItem['@type'] != 'Occupation':
continue
occupationItem['skills'] = skillsList
return True
return False

View File

@ -8,6 +8,7 @@ __status__ = "Production"
import os import os
from pprint import pprint from pprint import pprint
from utils import getOccupationName
from utils import getLockedAccount from utils import getLockedAccount
from utils import hasUsersPath from utils import hasUsersPath
from utils import getFullDomain from utils import getFullDomain
@ -741,8 +742,7 @@ def htmlProfile(rssIconAtTop: bool,
joinedDate = profileJson['published'] joinedDate = profileJson['published']
occupationName = None occupationName = None
if profileJson.get('hasOccupation'): if profileJson.get('hasOccupation'):
if profileJson['hasOccupation'].get('name'): occupationName = getOccupationName(profileJson)
occupationName = profileJson['hasOccupation']['name']
avatarUrl = profileJson['icon']['url'] avatarUrl = profileJson['icon']['url']
@ -1602,8 +1602,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
occupationName = '' occupationName = ''
if actorJson.get('hasOccupation'): if actorJson.get('hasOccupation'):
if actorJson['hasOccupation'].get('name'): occupationName = getOccupationName(actorJson)
occupationName = actorJson['hasOccupation']['name']
editProfileForm += '<label class="labels">' + \ editProfileForm += '<label class="labels">' + \
translate['Occupation'] + ':</label><br>\n' translate['Occupation'] + ':</label><br>\n'