Skip to content
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
3 changes: 1 addition & 2 deletions lib/Db/WatchMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

namespace OCA\Polls\Db;

use OCA\Polls\AppConstants;
use OCA\Polls\UserSession;
use OCP\AppFramework\Db\QBMapper;
use OCP\IDBConnection;
Expand Down Expand Up @@ -42,7 +41,7 @@ public function findUpdatesForPollId(int $pollId, int $offset): array {
)
->andWhere($qb->expr()->orX(
$qb->expr()->eq('poll_id', $qb->createNamedParameter($pollId)),
$qb->expr()->eq('table', $qb->createNamedParameter(AppConstants::APP_ID))
$qb->expr()->eq('table', $qb->createNamedParameter(Watch::OBJECT_POLLS))
));

return $this->findEntities($qb);
Expand Down
9 changes: 8 additions & 1 deletion src/Exceptions/Exceptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ class NotReady extends Error {
}
}

class NotAllowed extends Error {
constructor(message: string | undefined) {
super(message)
this.name = 'NotAllowed'
}
}

class InvalidJSON extends Error {
constructor(message: string | undefined) {
super(message)
this.name = 'InvalidJSON'
}
}

export { Exception, InvalidJSON, NotReady }
export { Exception, InvalidJSON, NotReady, NotAllowed }
26 changes: 22 additions & 4 deletions src/composables/usePollWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
} from './usePollWatcher.types'

import type { Watcher } from '../stores/session.types'
import { NotAllowed } from '../Exceptions/Exceptions'

/**
* poll watcher to keep polls collection and the current poll
Expand Down Expand Up @@ -179,14 +180,31 @@ export const usePollWatcher = (interval = 30000) => {
const handleWatcherTasks = (tasks: string[]) => {
Logger.info('[PollWatcher] Tasks to handle:', { tasks })

tasks.forEach((task: string) => {
tasks.forEach(async (task: string) => {
switch (task) {
case 'shares':
sharesStore.load()
try {
await sharesStore.load()
} catch (error) {
if ((error as NotAllowed).name === 'NotAllowed') {
// User is not allowed to load shares.
// instead assume a changed share affecting the user.
// Reload the session context to update the share
sessionStore.load()
return
}
Logger.error('Error loading poll shares', { error })
}
break
case 'polls':
pollStore.load()
pollsStore.load()
try {
await pollsStore.load()
} catch (error) {
if ((error as NotAllowed).name === 'NotAllowed') {
return
}
Logger.error('Error loading polls list', { error })
}
break
case 'votes':
votesStore.load()
Expand Down
11 changes: 10 additions & 1 deletion src/stores/polls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
FilterType,
SortType,
} from './polls.types'
import { NotAllowed } from '../Exceptions/Exceptions'

export const sortColumnsMapping: { [key in SortType]: string } = {
created: 'status.created',
Expand Down Expand Up @@ -312,7 +313,13 @@ export const usePollsStore = defineStore('polls', {
* @return {Promise<void>}
*/
async load(forced: boolean = true): Promise<void> {
const pollGroupsStore = usePollGroupsStore()
const sessionStore = useSessionStore()

if (!sessionStore.userStatus.isLoggedin) {
this.polls = []
this.meta.status = ''
throw new NotAllowed('Not allowed to load polls; not logged in')
}

if (
this.meta.status === 'loading'
Expand All @@ -327,6 +334,8 @@ export const usePollsStore = defineStore('polls', {

this.meta.status = 'loading'

const pollGroupsStore = usePollGroupsStore()

try {
const response = await PollsAPI.getPolls()
this.polls = response.data.polls
Expand Down
15 changes: 15 additions & 0 deletions src/stores/shares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import type {
SharePurpose,
PublicPollEmailConditions,
} from './shares.types'
import { usePollStore } from './poll'
import { NotAllowed } from '../Exceptions/Exceptions'

export const useSharesStore = defineStore('shares', {
state: (): SharesStore => ({
Expand Down Expand Up @@ -69,6 +71,14 @@ export const useSharesStore = defineStore('shares', {

if (purpose === 'pollGroup') {
const pollGroupsStore = usePollGroupsStore()
if (
pollGroupsStore.currentPollGroup?.owner.id
!== useSessionStore().currentUser.id
) {
this.shares = []
throw new NotAllowed('Not allowed to load shares for this group')
}

Logger.info('Loading group shares')
// For group shares, we need to use the current poll group ID

Expand All @@ -77,6 +87,11 @@ export const useSharesStore = defineStore('shares', {
}
pollOrPollGroupId = pollGroupsStore.currentPollGroup.id
} else {
const pollStore = usePollStore()
if (!pollStore.permissions.edit) {
this.shares = []
throw new NotAllowed('Not allowed to load shares for this poll')
}
Logger.info('Loading poll shares')
// For regular poll shares, we use the current poll ID
const sessionStore = useSessionStore()
Expand Down
6 changes: 5 additions & 1 deletion src/stores/votes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ export const useVotesStore = defineStore('votes', {
(user) => user.id === sessionStore.currentUser?.id,
)

if (currentUserIndex < 0 && !pollStore.status.isExpired) {
if (
currentUserIndex < 0
&& !pollStore.status.isExpired
&& sessionStore.currentUser.type !== 'public'
) {
// add current user to the begining of the list if not already present
// and if the poll is not expired
participants.unshift(sessionStore.currentUser)
Expand Down
7 changes: 6 additions & 1 deletion src/views/Vote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { useSubscriptionStore } from '../stores/subscription'

import type { CollapsibleProps } from '../components/Base/modules/Collapsible.vue'
import { Event } from '../Types'
import { loadContext } from '../composables/context'

const pollStore = usePollStore()
const optionsStore = useOptionsStore()
Expand Down Expand Up @@ -156,7 +157,11 @@ async function resetPoll() {
subscriptionStore.$reset()
}

onBeforeRouteUpdate(async () => {
onBeforeRouteUpdate(async (to, from) => {
if (to.name === 'publicVote' && to.params.token !== from.params.token) {
loadContext(to)
// Same poll, no need to reload
}
loadPoll(true)
})

Expand Down
2 changes: 1 addition & 1 deletion src/workers/pollWatcher.worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ self.onmessage = async (props: MessageEvent<WatcherProps>) => {
status: 'idle',
mode,
interval,
message: `[Worker] Sleeping for .${Math.floor(interval / 1000)} s`,
message: `[Worker] Sleeping for ${Math.floor(interval / 1000)} s`,
})
await sleep(interval)
}
Expand Down