Skip to content

Commit

Permalink
Merge pull request #204 from NikitaMic/develop
Browse files Browse the repository at this point in the history
Poll Plugin
  • Loading branch information
kreinhard authored Aug 10, 2023
2 parents 20492b4 + 90154f8 commit 96dbf0b
Show file tree
Hide file tree
Showing 26 changed files with 3,262 additions and 602 deletions.
496 changes: 279 additions & 217 deletions projectforge-application/src/main/resources/i18nKeys.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,6 @@ public boolean hasInsertAccess(final PFUserDO user) {
public boolean hasLoggedInUserUpdateAccess(final O obj, final O dbObj, final boolean throwException) {
return hasUpdateAccess(ThreadLocalUserContext.getUser(), obj, dbObj, throwException);
}

/**
* Checks update access right by calling hasAccess(obj, OperationType.UPDATE).
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2023 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.poll

import org.hibernate.search.annotations.Indexed
import org.projectforge.business.poll.filter.PollAssignment
import org.projectforge.business.poll.filter.PollState
import org.projectforge.common.StringHelper
import org.projectforge.common.anots.PropertyInfo
import org.projectforge.framework.persistence.api.AUserRightId
import org.projectforge.framework.persistence.entities.DefaultBaseDO
import org.projectforge.framework.persistence.user.api.ThreadLocalUserContext
import org.projectforge.framework.persistence.user.entities.PFUserDO
import org.springframework.context.annotation.DependsOn
import java.time.LocalDate
import javax.persistence.*


@Entity
@Indexed
@Table(name = "t_poll")
@AUserRightId(value = "poll", checkAccess = false)
@DependsOn("org.projectforge.framework.persistence.user.entities.PFUserDO")
open class PollDO : DefaultBaseDO() {

@PropertyInfo(i18nKey = "poll.title")
@get:Column(name = "title", nullable = false, length = 1000)
open var title: String? = null

@PropertyInfo(i18nKey = "poll.description")
@get:Column(name = "description", length = 10000)
open var description: String? = null

@get:PropertyInfo(i18nKey = "poll.owner")
@get:ManyToOne(fetch = FetchType.LAZY)
@get:JoinColumn(name = "owner_fk", nullable = false)
open var owner: PFUserDO? = null

@PropertyInfo(i18nKey = "poll.location")
@get:Column(name = "location")
open var location: String? = null

@PropertyInfo(i18nKey = "poll.deadline")
@get:Column(name = "deadline", nullable = false)
open var deadline: LocalDate? = null


@PropertyInfo(i18nKey = "poll.attendees")
@get:Column(name = "attendeeIds", nullable = true)
open var attendeeIds: String? = null

@PropertyInfo(i18nKey = "poll.attendee_groups")
@get:Column(name = "groupAttendeeIds", nullable = true)
open var groupAttendeeIds: String? = null

@PropertyInfo(i18nKey = "poll.full_access_groups")
@get:Column(name = "full_access_group_ids", length = 4000, nullable = true)
open var fullAccessGroupIds: String? = null

@PropertyInfo(i18nKey = "poll.full_access_user")
@get:Column(name = "full_access_user_ids", length = 4000, nullable = true)
open var fullAccessUserIds: String? = null

@PropertyInfo(i18nKey = "poll.inputFields")
@get:Column(name = "inputFields", length = 1000)
open var inputFields: String? = null

@PropertyInfo(i18nKey = "poll.state")
@get:Column(name = "state", nullable = false)
open var state: State = State.RUNNING

@Transient
fun getPollAssignment(): MutableList<PollAssignment> {
val currentUserId = ThreadLocalUserContext.userId!!
val assignmentList = mutableListOf<PollAssignment>()
if (currentUserId == this.owner?.id) {
assignmentList.add(PollAssignment.OWNER)
}
val accessUserIds = toIntArray(this.fullAccessUserIds)
if (accessUserIds?.contains(currentUserId) == true) {
assignmentList.add(PollAssignment.ACCESS)
}
val attendeeUserIds = toIntArray(this.attendeeIds)
if (attendeeUserIds?.contains(currentUserId) == true) {
assignmentList.add(PollAssignment.ATTENDEE)
}
if (assignmentList.isEmpty())
assignmentList.add(PollAssignment.OTHER)

return assignmentList
}

@Transient
fun getPollStatus(): PollState {
return if (this.state == State.FINISHED) {
PollState.FINISHED
} else if (this.state == State.RUNNING) {
PollState.RUNNING
} else {
PollState.FINISHED_AND_MAIL_SENT
}
}

enum class State {
RUNNING, FINISHED, FINISHED_AND_MAIL_SENT
}

companion object {
fun toIntArray(str: String?): IntArray? {
if (str.isNullOrBlank()) return null
return StringHelper.splitToInts(str, ",", false)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2023 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.poll

import org.projectforge.business.group.service.GroupService
import org.projectforge.framework.access.OperationType
import org.projectforge.framework.persistence.api.BaseDao
import org.projectforge.framework.persistence.user.api.ThreadLocalUserContext
import org.projectforge.framework.persistence.user.entities.PFUserDO
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Repository

@Repository
open class PollDao : BaseDao<PollDO>(PollDO::class.java) {

@Autowired
private lateinit var groupService: GroupService

override fun newInstance(): PollDO {
return PollDO()
}

override fun hasAccess(
user: PFUserDO?,
obj: PollDO?,
oldObj: PollDO?,
operationType: OperationType?,
throwException: Boolean
): Boolean {

if (obj == null && operationType == OperationType.SELECT) {
return true
};
if (obj != null && operationType == OperationType.SELECT) {
if (hasFullAccess(obj) || isAttendee(obj, ThreadLocalUserContext.user?.id!!))
return true
}
if (obj != null) {
return hasFullAccess(obj)
}
return false
}

// returns true if current user has full access, otherwise returns false
fun hasFullAccess(obj: PollDO): Boolean {
val loggedInUserId = ThreadLocalUserContext.userId!!
if (!obj.fullAccessUserIds.isNullOrBlank()) {
val userIdArray = PollDO.toIntArray(obj.fullAccessUserIds)
if (userIdArray?.contains(loggedInUserId) == true) {
return true
}
}
if (obj.owner?.id == loggedInUserId) {
return true
}
if (!obj.fullAccessGroupIds.isNullOrBlank()) {
val groupIdArray = PollDO.toIntArray(obj.fullAccessGroupIds)
val groupUsers = groupService.getGroupUsers(groupIdArray)
groupUsers.map { it.id }.forEach { id ->
if (id == loggedInUserId) {
return true
}
}
}
return false
}

fun isAttendee(obj: PollDO, user: Int): Boolean {
return PollDO.toIntArray(obj.attendeeIds)?.contains(user) == true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2023 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.poll

import org.hibernate.search.annotations.Indexed
import org.projectforge.common.anots.PropertyInfo
import org.projectforge.framework.persistence.api.AUserRightId
import org.projectforge.framework.persistence.entities.DefaultBaseDO
import org.projectforge.framework.persistence.user.entities.PFUserDO
import org.springframework.context.annotation.DependsOn
import javax.persistence.*

@Entity
@Indexed
@Table(name = "t_poll_response")
@AUserRightId(value = "poll.response", checkAccess = false)
@DependsOn("org.projectforge.framework.persistence.user.entities.PFUserDO")
open class PollResponseDO : DefaultBaseDO() {

@get:PropertyInfo(i18nKey = "poll.response.poll")
@get:ManyToOne(fetch = FetchType.LAZY)
@get:JoinColumn(name = "poll_fk", nullable = false)
open var poll: PollDO? = null

@get:PropertyInfo(i18nKey = "poll.response.owner")
@get:ManyToOne(fetch = FetchType.LAZY)
@get:JoinColumn(name = "owner_fk", nullable = false)
open var owner: PFUserDO? = null

@PropertyInfo(i18nKey = "poll.responses")
@get:Column(name = "responses", nullable = true, length = 1000)
open var responses: String? = null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2023 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.poll

import org.projectforge.framework.access.OperationType
import org.projectforge.framework.persistence.api.BaseDao
import org.projectforge.framework.persistence.user.entities.PFUserDO
import org.springframework.stereotype.Repository

@Repository
open class PollResponseDao : BaseDao<PollResponseDO>(PollResponseDO::class.java) {
override fun newInstance(): PollResponseDO {
return PollResponseDO()
}

override fun hasAccess(
user: PFUserDO?,
obj: PollResponseDO?,
oldObj: PollResponseDO?,
operationType: OperationType?,
throwException: Boolean
): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2023 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.poll.filter

import org.projectforge.common.i18n.I18nEnum

enum class PollAssignment(val key: String) : I18nEnum {
OWNER("owner"), ACCESS("access"), ATTENDEE("attendee"), OTHER("other");

override val i18nKey: String
get() = ("poll.$key")
}
Loading

0 comments on commit 96dbf0b

Please sign in to comment.