From e03b2e0fd8da8be2fadbd5554db2b1caade4cbaf Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 14:01:22 +0000 Subject: [PATCH 1/9] Set a flag to clear the browser cache when the theme is changed --- theme.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/theme.py b/theme.py index 9a27ec6e6..dbf78cf27 100644 --- a/theme.py +++ b/theme.py @@ -619,6 +619,15 @@ def setNewsAvatar(baseDir: str, name: str, nickname + '@' + domain + '/avatar.png') +def _setClearCacheFlag(baseDir: str) -> None: + """Sets a flag which can be used by an external system + (eg. a script in a cron job) to clear the browser cache + """ + flagFilename = baseDir + '/accounts/.clear_cache' + with open(flagFilename, 'w+') as flagFile: + flagFile.write('\n') + + def setTheme(baseDir: str, name: str, domain: str, allowLocalNetworkAccess: bool) -> bool: """Sets the theme with the given name as the current theme @@ -674,4 +683,5 @@ def setTheme(baseDir: str, name: str, domain: str, disableGrayscale(baseDir) _setThemeInConfig(baseDir, name) + _setClearCacheFlag(baseDir) return result From 0dbd048a1516bcdf07a1a3200f879d781609f220 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:29:22 +0000 Subject: [PATCH 2/9] Check authorization on person options --- daemon.py | 11 +- webapp_person_options.py | 229 ++++++++++++++++++++------------------- 2 files changed, 125 insertions(+), 115 deletions(-) diff --git a/daemon.py b/daemon.py index d2029b346..b147c100d 100644 --- a/daemon.py +++ b/daemon.py @@ -2819,7 +2819,7 @@ class PubServer(BaseHTTPRequestHandler): domain, domainFull, GETstartTime, GETtimings, onionDomain, i2pDomain, - cookie, debug) + cookie, debug, authorized) return else: showPublishedDateOnly = self.server.showPublishedDateOnly @@ -5486,7 +5486,8 @@ class PubServer(BaseHTTPRequestHandler): domain: str, domainFull: str, GETstartTime, GETtimings: {}, onionDomain: str, i2pDomain: str, - cookie: str, debug: bool) -> None: + cookie: str, debug: bool, + authorized: bool) -> None: """Show person options screen """ backToPath = '' @@ -5576,7 +5577,8 @@ class PubServer(BaseHTTPRequestHandler): lockedAccount, movedTo, alsoKnownAs, self.server.textModeBanner, - self.server.newsInstance).encode('utf-8') + self.server.newsInstance, + authorized).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -10495,7 +10497,8 @@ class PubServer(BaseHTTPRequestHandler): GETstartTime, GETtimings, self.server.onionDomain, self.server.i2pDomain, - cookie, self.server.debug) + cookie, self.server.debug, + authorized) return self._benchmarkGETtimings(GETstartTime, GETtimings, diff --git a/webapp_person_options.py b/webapp_person_options.py index 75dd21045..5c903ce9b 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -53,7 +53,8 @@ def htmlPersonOptions(defaultTimeline: str, movedTo: str, alsoKnownAs: [], textModeBanner: str, - newsInstance: bool) -> str: + newsInstance: bool, + authorized: bool) -> str: """Show options for a person: view/follow/block/report """ optionsDomain, optionsPort = getDomainFromActor(optionsActor) @@ -225,88 +226,91 @@ def htmlPersonOptions(defaultTimeline: str, optionsActor + '">\n' optionsStr += ' \n' - if optionsNickname: - handle = optionsNickname + '@' + optionsDomainFull - petname = getPetName(baseDir, nickname, domain, handle) - optionsStr += \ - ' ' + translate['Petname'] + ': \n' + \ - ' \n' \ - '
\n' + if authorized: + if optionsNickname: + handle = optionsNickname + '@' + optionsDomainFull + petname = getPetName(baseDir, nickname, domain, handle) + optionsStr += \ + ' ' + translate['Petname'] + ': \n' + \ + ' \n' \ + '
\n' - # checkbox for receiving calendar events - if isFollowingActor(baseDir, nickname, domain, optionsActor): - checkboxStr = \ - ' ' + \ - translate['Receive calendar events from this account'] + \ - '\n
\n' - if not receivingCalendarEvents(baseDir, nickname, domain, - optionsNickname, optionsDomainFull): - checkboxStr = checkboxStr.replace(' checked>', '>') - optionsStr += checkboxStr + # checkbox for receiving calendar events + if isFollowingActor(baseDir, nickname, domain, optionsActor): + checkboxStr = \ + ' ' + \ + translate['Receive calendar events from this account'] + \ + '\n
\n' + if not receivingCalendarEvents(baseDir, nickname, domain, + optionsNickname, + optionsDomainFull): + checkboxStr = checkboxStr.replace(' checked>', '>') + optionsStr += checkboxStr - # checkbox for permission to post to newswire - newswirePostsPermitted = False - if optionsDomainFull == domainFull: - adminNickname = getConfigParam(baseDir, 'admin') - if (nickname == adminNickname or - (isModerator(baseDir, nickname) and - not isModerator(baseDir, optionsNickname))): - newswireBlockedFilename = \ + # checkbox for permission to post to newswire + newswirePostsPermitted = False + if optionsDomainFull == domainFull: + adminNickname = getConfigParam(baseDir, 'admin') + if (nickname == adminNickname or + (isModerator(baseDir, nickname) and + not isModerator(baseDir, optionsNickname))): + newswireBlockedFilename = \ + baseDir + '/accounts/' + \ + optionsNickname + '@' + optionsDomain + '/.nonewswire' + checkboxStr = \ + ' ' + \ + translate['Allow news posts'] + \ + '\n
\n' + if os.path.isfile(newswireBlockedFilename): + checkboxStr = checkboxStr.replace(' checked>', '>') + else: + newswirePostsPermitted = True + optionsStr += checkboxStr + + # whether blogs created by this account are moderated on the newswire + if newswirePostsPermitted: + moderatedFilename = \ baseDir + '/accounts/' + \ - optionsNickname + '@' + optionsDomain + '/.nonewswire' + optionsNickname + '@' + optionsDomain + '/.newswiremoderated' checkboxStr = \ ' ' + \ - translate['Allow news posts'] + \ + 'class="profilecheckbox" name="modNewsPosts" checked> ' + \ + translate['News posts are moderated'] + \ '\n
\n' - if os.path.isfile(newswireBlockedFilename): - checkboxStr = checkboxStr.replace(' checked>', '>') - else: - newswirePostsPermitted = True - optionsStr += checkboxStr - - # whether blogs created by this account are moderated on the newswire - if newswirePostsPermitted: - moderatedFilename = \ - baseDir + '/accounts/' + \ - optionsNickname + '@' + optionsDomain + '/.newswiremoderated' - checkboxStr = \ - ' ' + \ - translate['News posts are moderated'] + \ - '\n
\n' - if not os.path.isfile(moderatedFilename): - checkboxStr = checkboxStr.replace(' checked>', '>') - optionsStr += checkboxStr - - # checkbox for permission to post to featured articles - if newsInstance and optionsDomainFull == domainFull: - adminNickname = getConfigParam(baseDir, 'admin') - if (nickname == adminNickname or - (isModerator(baseDir, nickname) and - not isModerator(baseDir, optionsNickname))): - checkboxStr = \ - ' ' + \ - translate['Featured writer'] + \ - '\n
\n' - if not isFeaturedWriter(baseDir, optionsNickname, - optionsDomain): + if not os.path.isfile(moderatedFilename): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr + # checkbox for permission to post to featured articles + if newsInstance and optionsDomainFull == domainFull: + adminNickname = getConfigParam(baseDir, 'admin') + if (nickname == adminNickname or + (isModerator(baseDir, nickname) and + not isModerator(baseDir, optionsNickname))): + checkboxStr = \ + ' ' + \ + translate['Featured writer'] + \ + '\n
\n' + if not isFeaturedWriter(baseDir, optionsNickname, + optionsDomain): + checkboxStr = checkboxStr.replace(' checked>', '>') + optionsStr += checkboxStr + optionsStr += optionsLinkStr backPath = '/' if nickname: @@ -317,49 +321,52 @@ def htmlPersonOptions(defaultTimeline: str, ' \n' - optionsStr += \ - ' \n' + if authorized: + optionsStr += \ + ' \n' optionsStr += donateStr - optionsStr += \ - ' \n' - optionsStr += \ - ' \n' - optionsStr += \ - ' \n' - optionsStr += \ - ' \n' - optionsStr += \ - ' \n' - - if isModerator(baseDir, nickname): + if authorized: + optionsStr += \ + ' \n' + optionsStr += \ + ' \n' + optionsStr += \ + ' \n' + optionsStr += \ + ' \n' optionsStr += \ ' \n' + 'name="submitReport">' + translate['Report'] + '\n' - personNotes = '' - personNotesFilename = \ - baseDir + '/accounts/' + nickname + '@' + domain + \ - '/notes/' + handle + '.txt' - if os.path.isfile(personNotesFilename): - with open(personNotesFilename, 'r') as fp: - personNotes = fp.read() + if isModerator(baseDir, nickname): + optionsStr += \ + ' \n' - optionsStr += \ - '

' + translate['Notes'] + ': \n' - optionsStr += '
\n' - optionsStr += \ - ' \n' + personNotes = '' + personNotesFilename = \ + baseDir + '/accounts/' + nickname + '@' + domain + \ + '/notes/' + handle + '.txt' + if os.path.isfile(personNotesFilename): + with open(personNotesFilename, 'r') as fp: + personNotes = fp.read() + + optionsStr += \ + '

' + translate['Notes'] + ': \n' + optionsStr += '
\n' + optionsStr += \ + ' \n' optionsStr += ' \n' optionsStr += '\n' From 8124a7cdc6fdab55bf996f1c817331258f2bb451 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:35:26 +0000 Subject: [PATCH 3/9] Check that notes belong to the viewer --- webapp_person_options.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 5c903ce9b..6459f2d45 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -351,12 +351,13 @@ def htmlPersonOptions(defaultTimeline: str, translate['Info'] + '\n' personNotes = '' - personNotesFilename = \ - baseDir + '/accounts/' + nickname + '@' + domain + \ - '/notes/' + handle + '.txt' - if os.path.isfile(personNotesFilename): - with open(personNotesFilename, 'r') as fp: - personNotes = fp.read() + if originPathStr.startswith('/' + nickname + '/'): + personNotesFilename = \ + baseDir + '/accounts/' + nickname + '@' + domain + \ + '/notes/' + handle + '.txt' + if os.path.isfile(personNotesFilename): + with open(personNotesFilename, 'r') as fp: + personNotes = fp.read() optionsStr += \ '

' + translate['Notes'] + ': \n' From 8e343f2ca0240b7dd74ef3773a541fc013105483 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:40:22 +0000 Subject: [PATCH 4/9] Users --- webapp_person_options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 6459f2d45..c7f18490a 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -351,7 +351,7 @@ def htmlPersonOptions(defaultTimeline: str, translate['Info'] + '\n' personNotes = '' - if originPathStr.startswith('/' + nickname + '/'): + if originPathStr.startswith('/users/' + nickname + '/'): personNotesFilename = \ baseDir + '/accounts/' + nickname + '@' + domain + \ '/notes/' + handle + '.txt' From 8635d68e3e1c571f6f0e7158d5ec23089fb54a3a Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:42:11 +0000 Subject: [PATCH 5/9] Debug --- webapp_person_options.py | 1 + 1 file changed, 1 insertion(+) diff --git a/webapp_person_options.py b/webapp_person_options.py index c7f18490a..3ee334b49 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -351,6 +351,7 @@ def htmlPersonOptions(defaultTimeline: str, translate['Info'] + '\n' personNotes = '' + print('originPathStr=' + originPathStr) if originPathStr.startswith('/users/' + nickname + '/'): personNotesFilename = \ baseDir + '/accounts/' + nickname + '@' + domain + \ From 2d861657957306787259cbba28dec42032f875fb Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:45:53 +0000 Subject: [PATCH 6/9] Origin check --- webapp_person_options.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 3ee334b49..5f824b3bc 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -351,8 +351,7 @@ def htmlPersonOptions(defaultTimeline: str, translate['Info'] + '\n' personNotes = '' - print('originPathStr=' + originPathStr) - if originPathStr.startswith('/users/' + nickname + '/'): + if originPathStr == '/users/' + nickname: personNotesFilename = \ baseDir + '/accounts/' + nickname + '@' + domain + \ '/notes/' + handle + '.txt' From 9145ac0801e226a3fec3ce54bb61e262904adc54 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:51:48 +0000 Subject: [PATCH 7/9] More checks on visibility of items on person options --- webapp_person_options.py | 152 ++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 74 deletions(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 5f824b3bc..176d75bdc 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -227,90 +227,94 @@ def htmlPersonOptions(defaultTimeline: str, optionsStr += ' \n' if authorized: - if optionsNickname: - handle = optionsNickname + '@' + optionsDomainFull - petname = getPetName(baseDir, nickname, domain, handle) - optionsStr += \ - ' ' + translate['Petname'] + ': \n' + \ - ' \n' \ - '
\n' + if originPathStr == '/users/' + nickname: + if optionsNickname: + handle = optionsNickname + '@' + optionsDomainFull + petname = getPetName(baseDir, nickname, domain, handle) + optionsStr += \ + ' ' + translate['Petname'] + ': \n' + \ + ' \n' \ + '
\n' - # checkbox for receiving calendar events - if isFollowingActor(baseDir, nickname, domain, optionsActor): - checkboxStr = \ - ' ' + \ - translate['Receive calendar events from this account'] + \ - '\n
\n' - if not receivingCalendarEvents(baseDir, nickname, domain, - optionsNickname, - optionsDomainFull): - checkboxStr = checkboxStr.replace(' checked>', '>') - optionsStr += checkboxStr + # checkbox for receiving calendar events + if isFollowingActor(baseDir, nickname, domain, optionsActor): + checkboxStr = \ + ' ' + \ + translate['Receive calendar events from this account'] + \ + '\n
\n' + if not receivingCalendarEvents(baseDir, nickname, domain, + optionsNickname, + optionsDomainFull): + checkboxStr = checkboxStr.replace(' checked>', '>') + optionsStr += checkboxStr - # checkbox for permission to post to newswire - newswirePostsPermitted = False - if optionsDomainFull == domainFull: - adminNickname = getConfigParam(baseDir, 'admin') - if (nickname == adminNickname or - (isModerator(baseDir, nickname) and - not isModerator(baseDir, optionsNickname))): - newswireBlockedFilename = \ + # checkbox for permission to post to newswire + newswirePostsPermitted = False + if optionsDomainFull == domainFull: + adminNickname = getConfigParam(baseDir, 'admin') + if (nickname == adminNickname or + (isModerator(baseDir, nickname) and + not isModerator(baseDir, optionsNickname))): + newswireBlockedFilename = \ + baseDir + '/accounts/' + \ + optionsNickname + '@' + optionsDomain + '/.nonewswire' + checkboxStr = \ + ' ' + \ + translate['Allow news posts'] + \ + '\n
\n' + if os.path.isfile(newswireBlockedFilename): + checkboxStr = checkboxStr.replace(' checked>', '>') + else: + newswirePostsPermitted = True + optionsStr += checkboxStr + + # whether blogs created by this account are moderated on + # the newswire + if newswirePostsPermitted: + moderatedFilename = \ baseDir + '/accounts/' + \ - optionsNickname + '@' + optionsDomain + '/.nonewswire' + optionsNickname + '@' + \ + optionsDomain + '/.newswiremoderated' checkboxStr = \ ' ' + \ - translate['Allow news posts'] + \ + 'class="profilecheckbox" name="modNewsPosts" checked> ' + \ + translate['News posts are moderated'] + \ '\n
\n' - if os.path.isfile(newswireBlockedFilename): - checkboxStr = checkboxStr.replace(' checked>', '>') - else: - newswirePostsPermitted = True - optionsStr += checkboxStr - - # whether blogs created by this account are moderated on the newswire - if newswirePostsPermitted: - moderatedFilename = \ - baseDir + '/accounts/' + \ - optionsNickname + '@' + optionsDomain + '/.newswiremoderated' - checkboxStr = \ - ' ' + \ - translate['News posts are moderated'] + \ - '\n
\n' - if not os.path.isfile(moderatedFilename): - checkboxStr = checkboxStr.replace(' checked>', '>') - optionsStr += checkboxStr - - # checkbox for permission to post to featured articles - if newsInstance and optionsDomainFull == domainFull: - adminNickname = getConfigParam(baseDir, 'admin') - if (nickname == adminNickname or - (isModerator(baseDir, nickname) and - not isModerator(baseDir, optionsNickname))): - checkboxStr = \ - ' ' + \ - translate['Featured writer'] + \ - '\n
\n' - if not isFeaturedWriter(baseDir, optionsNickname, - optionsDomain): + if not os.path.isfile(moderatedFilename): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr + # checkbox for permission to post to featured articles + if newsInstance and optionsDomainFull == domainFull: + adminNickname = getConfigParam(baseDir, 'admin') + if (nickname == adminNickname or + (isModerator(baseDir, nickname) and + not isModerator(baseDir, optionsNickname))): + checkboxStr = \ + ' ' + \ + translate['Featured writer'] + \ + '\n
\n' + if not isFeaturedWriter(baseDir, optionsNickname, + optionsDomain): + checkboxStr = checkboxStr.replace(' checked>', '>') + optionsStr += checkboxStr + optionsStr += optionsLinkStr backPath = '/' if nickname: From 4e6d9d2d4561ea8864ce0cbf31f1fbefc9bc2aba Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Feb 2021 17:58:52 +0000 Subject: [PATCH 8/9] Change behavior of back button if not logged in --- webapp_person_options.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/webapp_person_options.py b/webapp_person_options.py index 176d75bdc..91f1c14bd 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -321,10 +321,16 @@ def htmlPersonOptions(defaultTimeline: str, backPath = '/users/' + nickname + '/' + defaultTimeline if 'moderation' in backToPath: backPath = '/users/' + nickname + '/moderation' - optionsStr += \ - ' \n' + if authorized: + optionsStr += \ + ' \n' + else: + optionsStr += \ + ' \n' if authorized: optionsStr += \ '