working on poll permissions
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -33,6 +33,7 @@ public class Path {
|
|||||||
|
|
||||||
public static final String PAGE = "page";
|
public static final String PAGE = "page";
|
||||||
public static final String PASSWORD = "password";
|
public static final String PASSWORD = "password";
|
||||||
|
public static final String PERMISSIONS = "permissions";
|
||||||
public static final String PROJECT = "project";
|
public static final String PROJECT = "project";
|
||||||
public static final String PROPERTIES = "properties";
|
public static final String PROPERTIES = "properties";
|
||||||
public static final String PROPERTY = "property";
|
public static final String PROPERTY = "property";
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public class Text {
|
|||||||
public static final Object OPTION = "option"
|
public static final Object OPTION = "option"
|
||||||
;
|
;
|
||||||
public static final String PATH = "path";
|
public static final String PATH = "path";
|
||||||
|
public static final String PERMISSION = "permission";
|
||||||
public static final String POLL = "poll";
|
public static final String POLL = "poll";
|
||||||
public static final String POLLS = "polls";
|
public static final String POLLS = "polls";
|
||||||
public static final String PROJECTS = "projects";
|
public static final String PROJECTS = "projects";
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public enum Permission implements Mappable {
|
|||||||
for (var p : Permission.values()){
|
for (var p : Permission.values()){
|
||||||
if (p.code == code) return p;
|
if (p.code == code) return p;
|
||||||
}
|
}
|
||||||
throw new InvalidParameterException(format("{0} is not a valid permission code"));
|
throw new InvalidParameterException(format("{0} is not a valid permission code",code));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public class Poll implements Mappable {
|
|||||||
public static class Option implements Mappable{
|
public static class Option implements Mappable{
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
Integer status;
|
Integer status;
|
||||||
private String description;
|
private String description;
|
||||||
private String name;
|
private String name;
|
||||||
@@ -28,7 +29,6 @@ public class Poll implements Mappable {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String description(){
|
public String description(){
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -104,11 +104,11 @@ public class Poll implements Mappable {
|
|||||||
return format("Option \"{0}\"",name);
|
return format("Option \"{0}\"",name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public static class Evaluation {
|
public static class Evaluation {
|
||||||
// Map<Option → Map<Weight → Count>>
|
// Map<Option → Map<Weight → Count>>
|
||||||
private HashMap<Integer,Map<Integer,Integer>> selections = new HashMap<>();
|
private HashMap<Integer,Map<Integer,Integer>> selections = new HashMap<>();
|
||||||
|
|
||||||
public void count(ResultSet rs) throws SQLException {
|
public void count(ResultSet rs) throws SQLException {
|
||||||
var optionId = rs.getInt(OPTION_ID);
|
var optionId = rs.getInt(OPTION_ID);
|
||||||
var userId = rs.getObject(USER_ID);
|
var userId = rs.getObject(USER_ID);
|
||||||
@@ -120,16 +120,17 @@ public class Poll implements Mappable {
|
|||||||
public HashMap<Integer, Map<Integer, Integer>> toMap() {
|
public HashMap<Integer, Map<Integer, Integer>> toMap() {
|
||||||
return selections;
|
return selections;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
private Owner owner;
|
private Owner owner;
|
||||||
|
|
||||||
private String id, name, description;
|
private String id, name, description;
|
||||||
|
|
||||||
private boolean isPrivate;
|
private boolean isPrivate;
|
||||||
private List<Option> options;
|
private List<Option> options;
|
||||||
private Map<Integer,String> weights;
|
private Map<Integer,String> weights;
|
||||||
private Map<UmbrellaUser,Long> shares;
|
private Map<UmbrellaUser,Permission> permissions;
|
||||||
private Set<String> dirtyFields = new HashSet<>();
|
private Set<String> dirtyFields = new HashSet<>();
|
||||||
public Poll(String id, Owner owner, String name, String description, boolean isPrivate, List<Option> options, Map<Integer,String> weights, Map<UmbrellaUser,Long> shares){
|
public Poll(String id, Owner owner, String name, String description, boolean isPrivate, List<Option> options, Map<Integer,String> weights){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -137,9 +138,8 @@ public class Poll implements Mappable {
|
|||||||
this.isPrivate = isPrivate;
|
this.isPrivate = isPrivate;
|
||||||
this.options = new ArrayList<>();
|
this.options = new ArrayList<>();
|
||||||
this.weights = new HashMap<>();
|
this.weights = new HashMap<>();
|
||||||
this.shares = new HashMap<>();
|
this.permissions = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String description(){
|
public String description(){
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -169,12 +169,12 @@ public class Poll implements Mappable {
|
|||||||
return isPrivate;
|
return isPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, Map<String, Object>> mapShares() {
|
private Map<Long, Map<String, Object>> mapPermissions() {
|
||||||
var result = new HashMap<Long,Map<String,Object>>();
|
var result = new HashMap<Long,Map<String,Object>>();
|
||||||
for (var entry : shares.entrySet()){
|
for (var entry : permissions.entrySet()){
|
||||||
var user = entry.getKey();
|
var user = entry.getKey();
|
||||||
var data = user.toMap();
|
var data = user.toMap();
|
||||||
data.put(Field.PERMISSION,entry.getValue());
|
data.put(Field.PERMISSION,entry.getValue().toMap());
|
||||||
result.put(user.id(),data);
|
result.put(user.id(),data);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -198,7 +198,7 @@ public class Poll implements Mappable {
|
|||||||
var isPrivate = rs.getBoolean(Field.PRIVATE);
|
var isPrivate = rs.getBoolean(Field.PRIVATE);
|
||||||
var owner = ModuleRegistry.userService().loadUser(userId);
|
var owner = ModuleRegistry.userService().loadUser(userId);
|
||||||
|
|
||||||
return new Poll(id,owner,name,description,isPrivate,new ArrayList<>(),new HashMap<>(),new HashMap<>());
|
return new Poll(id,owner,name,description,isPrivate,new ArrayList<>(),new HashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Option> options(){
|
public List<Option> options(){
|
||||||
@@ -209,14 +209,20 @@ public class Poll implements Mappable {
|
|||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Poll setPrivate(boolean newValue) {
|
||||||
|
if (newValue != isPrivate) dirtyFields.add(PRIVATE);
|
||||||
|
isPrivate = newValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Poll setWeight(Integer weight, String description) {
|
public Poll setWeight(Integer weight, String description) {
|
||||||
weights.put(weight,description);
|
weights.put(weight,description);
|
||||||
dirtyFields.add(WEIGHTS);
|
dirtyFields.add(WEIGHTS);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<UmbrellaUser, Long> shares(){
|
public Map<UmbrellaUser, Permission> permissions(){
|
||||||
return shares;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -230,7 +236,7 @@ public class Poll implements Mappable {
|
|||||||
Field.RENDERED,Util.markdown(description)
|
Field.RENDERED,Util.markdown(description)
|
||||||
),
|
),
|
||||||
Field.OPTIONS, options.stream().collect(Collectors.toMap(Option::id,Option::toMap)),
|
Field.OPTIONS, options.stream().collect(Collectors.toMap(Option::id,Option::toMap)),
|
||||||
Field.SHARES, mapShares(),
|
Field.PERMISSION, mapPermissions(),
|
||||||
Field.PRIVATE, isPrivate,
|
Field.PRIVATE, isPrivate,
|
||||||
Field.WEIGHTS, weights
|
Field.WEIGHTS, weights
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each sortedMembers as member,i}
|
{#each sortedMembers as member (member.user.id)}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{member.user.name}</td>
|
<td>{member.user.name}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -12,20 +12,33 @@
|
|||||||
import { user } from '../../user.svelte.js';
|
import { user } from '../../user.svelte.js';
|
||||||
|
|
||||||
let { id } = $props();
|
let { id } = $props();
|
||||||
|
let visible_to_guests = false;
|
||||||
let new_option = $state({name:'',description:{'source':'',rendered:''}});
|
let new_option = $state({name:'',description:{'source':'',rendered:''}});
|
||||||
let new_weight = $state({description:'',weight:0});
|
let new_weight = $state({description:'',weight:0});
|
||||||
let poll = $state(null);
|
let poll = $state(null);
|
||||||
|
let members = $state([]);
|
||||||
|
|
||||||
function addMember(member){
|
function addMember(member){
|
||||||
for (let [id,name] of Object.entries(member)) update_permissions({user_id:id,permission:1});
|
for (let [id,name] of Object.entries(member)) update_permissions({user_id:+id,permission:4});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dropMember(member){
|
||||||
|
let user_id = member.user.id;
|
||||||
|
if (update_permissions({user_id,permission:0})){
|
||||||
|
members = members.filter(m => m.user.id != user_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function load(){
|
async function load(){
|
||||||
let url = api('poll/'+id);
|
let url = api('poll/'+id);
|
||||||
let res = await get(url);
|
let res = await get(url);
|
||||||
if (res.ok){
|
if (res.ok){
|
||||||
poll = await res.json();
|
poll = await res.json();
|
||||||
|
for (let perm of Object.values(poll.permission)){
|
||||||
|
members.push({ user : { name : perm.name, id : perm.id }, permission: { name : perm.permission.name, code: perm.permission.code}});
|
||||||
|
}
|
||||||
|
visible_to_guests = !poll.private;
|
||||||
yikes();
|
yikes();
|
||||||
} else error(res);
|
} else error(res);
|
||||||
}
|
}
|
||||||
@@ -71,7 +84,6 @@
|
|||||||
const weights = json.weights;
|
const weights = json.weights;
|
||||||
for (let weight of Object.keys(data)){
|
for (let weight of Object.keys(data)){
|
||||||
let desc = data[weight];
|
let desc = data[weight];
|
||||||
console.log(weight, desc);
|
|
||||||
if (desc) {
|
if (desc) {
|
||||||
poll.weights[weight] = desc;
|
poll.weights[weight] = desc;
|
||||||
} else delete poll.weights[weight]; // TODO: this corrupts the display of the following element!
|
} else delete poll.weights[weight]; // TODO: this corrupts the display of the following element!
|
||||||
@@ -100,11 +112,19 @@
|
|||||||
patch_weight(data);
|
patch_weight(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggle_guest(e){
|
||||||
|
patch_poll('private',!visible_to_guests);
|
||||||
|
}
|
||||||
|
|
||||||
async function update_permissions(data){
|
async function update_permissions(data){
|
||||||
let url = api(`poll/${id}/permissions`);
|
let url = api(`poll/${id}/permissions`);
|
||||||
let res = await post(url,data);
|
let res = await post(url,data);
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
yikes();
|
yikes();
|
||||||
|
let json = await res.json();
|
||||||
|
members = members.filter(m => m.user.id != json.user.id);
|
||||||
|
members.push(json);
|
||||||
|
console.log({members});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
error(res);
|
error(res);
|
||||||
@@ -128,7 +148,11 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{t('permissions')}</legend>
|
<legend>{t('permissions')}</legend>
|
||||||
<Permissions members={{}} {addMember} />
|
<Permissions {addMember} {members} {dropMember} updatePermission={(user_id,perm) => update_permissions({user_id,permission:perm.code})} />
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" bind:checked={visible_to_guests} onchange={toggle_guest} />
|
||||||
|
{t('visible_to_guests')}
|
||||||
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{t('options')}</legend>
|
<legend>{t('options')}</legend>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function share(poll){
|
function share(poll){
|
||||||
|
router.navigate(`/poll/${poll.id}/share`);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(load);
|
onMount(load);
|
||||||
@@ -70,10 +70,10 @@
|
|||||||
<td>{@html poll.description.rendered}</td>
|
<td>{@html poll.description.rendered}</td>
|
||||||
<td onclick={e => open(poll)}>{poll.owner.name}</td>
|
<td onclick={e => open(poll)}>{poll.owner.name}</td>
|
||||||
<td>
|
<td>
|
||||||
{#if user.id == poll.owner.id || poll.shares[user.id].permission == 2}
|
{#if user.id == poll.owner.id || poll.permission[user.id].permission == 2}
|
||||||
<button onclick={e => edit(poll)}>{t('edit')}</button>
|
<button onclick={e => edit(poll)}>{t('edit')}</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if user.id == poll.owner.id || poll.shares[user.id].permission > 0}
|
{#if user.id == poll.owner.id || poll.permission[user.id].permission > 0}
|
||||||
<button onclick={e => evaluate(poll)}>{t('evaluate')}</button>
|
<button onclick={e => evaluate(poll)}>{t('evaluate')}</button>
|
||||||
{/if}
|
{/if}
|
||||||
<button onclick={e => share(poll)}>{t('share')}</button>
|
<button onclick={e => share(poll)}>{t('share')}</button>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.poll;
|
package de.srsoftware.umbrella.poll;
|
||||||
|
|
||||||
|
import de.srsoftware.umbrella.core.model.Permission;
|
||||||
import de.srsoftware.umbrella.core.model.Poll;
|
import de.srsoftware.umbrella.core.model.Poll;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -11,12 +11,14 @@ import java.util.Map;
|
|||||||
public interface PollDb {
|
public interface PollDb {
|
||||||
Collection<Poll> listPolls(UmbrellaUser user);
|
Collection<Poll> listPolls(UmbrellaUser user);
|
||||||
|
|
||||||
|
Poll.Evaluation loadEvaluation(String id);
|
||||||
|
|
||||||
Poll loadPoll(String id);
|
Poll loadPoll(String id);
|
||||||
|
|
||||||
Poll save(Poll poll);
|
Poll save(Poll poll);
|
||||||
|
|
||||||
void saveSelection(Poll poll, Map<Integer,Integer> optionsToWeights, String guestName);
|
void saveSelection(Poll poll, Map<Integer,Integer> optionsToWeights, String guestName);
|
||||||
|
|
||||||
void saveSelection(Poll poll, Map<Integer,Integer> optionsToWeights, UmbrellaUser user);
|
void saveSelection(Poll poll, Map<Integer,Integer> optionsToWeights, UmbrellaUser user);
|
||||||
|
|
||||||
Poll.Evaluation loadEvaluation(String id);
|
void setPermission(String pollId, UmbrellaUser userId, Permission permission);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ package de.srsoftware.umbrella.poll;
|
|||||||
|
|
||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.FIELD;
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.ID;
|
|
||||||
import static de.srsoftware.umbrella.core.constants.Path.*;
|
import static de.srsoftware.umbrella.core.constants.Path.*;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Path.WEIGHT;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static de.srsoftware.umbrella.poll.Constants.CONFIG_DATABASE;
|
import static de.srsoftware.umbrella.poll.Constants.CONFIG_DATABASE;
|
||||||
import static java.lang.System.Logger.Level.WARNING;
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
import static java.net.HttpURLConnection.HTTP_OK;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
|
import static de.srsoftware.umbrella.core.model.Permission.READ_ONLY;
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.configuration.Configuration;
|
import de.srsoftware.configuration.Configuration;
|
||||||
import de.srsoftware.tools.Path;
|
import de.srsoftware.tools.Path;
|
||||||
@@ -21,6 +22,7 @@ import de.srsoftware.umbrella.core.api.PollService;
|
|||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import de.srsoftware.umbrella.core.constants.Text;
|
import de.srsoftware.umbrella.core.constants.Text;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
|
import de.srsoftware.umbrella.core.model.Permission;
|
||||||
import de.srsoftware.umbrella.core.model.Poll;
|
import de.srsoftware.umbrella.core.model.Poll;
|
||||||
import de.srsoftware.umbrella.core.model.Token;
|
import de.srsoftware.umbrella.core.model.Token;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
@@ -119,8 +121,8 @@ public class PollModule extends BaseHandler implements PollService {
|
|||||||
var poll = pollDb.loadPoll(pollId);
|
var poll = pollDb.loadPoll(pollId);
|
||||||
var permitted = user.equals(poll.owner());
|
var permitted = user.equals(poll.owner());
|
||||||
if (!permitted) {
|
if (!permitted) {
|
||||||
var permission = poll.shares().get(user);
|
var permission = poll.permissions().get(user);
|
||||||
if (permission == null || permission < 2) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
|
if (permission == null || permission == READ_ONLY) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
|
||||||
}
|
}
|
||||||
return poll;
|
return poll;
|
||||||
}
|
}
|
||||||
@@ -144,6 +146,8 @@ public class PollModule extends BaseHandler implements PollService {
|
|||||||
poll.description(json.getString(key)); break;
|
poll.description(json.getString(key)); break;
|
||||||
case Field.NAME:
|
case Field.NAME:
|
||||||
poll.name(json.getString(key)); break;
|
poll.name(json.getString(key)); break;
|
||||||
|
case PRIVATE:
|
||||||
|
poll.setPrivate(json.getBoolean(key)); break;
|
||||||
case null, default:
|
case null, default:
|
||||||
throw UmbrellaException.badRequest(Text.UNKNOWN_FIELD,ID,key);
|
throw UmbrellaException.badRequest(Text.UNKNOWN_FIELD,ID,key);
|
||||||
}
|
}
|
||||||
@@ -194,7 +198,7 @@ public class PollModule extends BaseHandler implements PollService {
|
|||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
if (!json.has(Field.NAME)) throw missingField(Field.NAME);
|
if (!json.has(Field.NAME)) throw missingField(Field.NAME);
|
||||||
var name = json.getString(Field.NAME);
|
var name = json.getString(Field.NAME);
|
||||||
var poll = new Poll(null,user,name,"",true, List.of(), Map.of(),Map.of());
|
var poll = new Poll(null,user,name,"",true, List.of(), Map.of());
|
||||||
return sendContent(ex,pollDb.save(poll));
|
return sendContent(ex,pollDb.save(poll));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,17 +207,40 @@ public class PollModule extends BaseHandler implements PollService {
|
|||||||
var poll = pollDb.loadPoll(id);
|
var poll = pollDb.loadPoll(id);
|
||||||
var permitted = user.equals(poll.owner());
|
var permitted = user.equals(poll.owner());
|
||||||
if (!permitted) {
|
if (!permitted) {
|
||||||
var permission = poll.shares().get(user);
|
var permission = poll.permissions().get(user);
|
||||||
if (permission == null || permission < 2) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
|
if (permission == null || permission == READ_ONLY) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
|
||||||
}
|
}
|
||||||
var head = path.pop();
|
var head = path.pop();
|
||||||
return switch (head){
|
return switch (head){
|
||||||
|
case PERMISSIONS -> postPermission(ex, poll, user);
|
||||||
case OPTION -> postOption(ex, poll);
|
case OPTION -> postOption(ex, poll);
|
||||||
case SELECT -> postSelection(ex, poll, user);
|
case SELECT -> postSelection(ex, poll, user);
|
||||||
case null, default -> notFound(ex);
|
case null, default -> notFound(ex);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean postPermission(HttpExchange ex, Poll poll, UmbrellaUser user) throws IOException {
|
||||||
|
LOG.log(WARNING,"Permission check not implemented for postPermission");
|
||||||
|
|
||||||
|
var json = json(ex);
|
||||||
|
if (!json.has(USER_ID)) throw missingField(USER_ID);
|
||||||
|
if (!json.has(PERMISSION)) throw missingField(PERMISSION);
|
||||||
|
if (!(json.get(USER_ID) instanceof Number userId)) throw invalidField(USER_ID,NUMBER);
|
||||||
|
if (!(json.get(PERMISSION) instanceof Number perm)) throw invalidField(PERMISSION,NUMBER);
|
||||||
|
var modifiedUser = userService().loadUser(userId.longValue());
|
||||||
|
if (perm.intValue() == 0){
|
||||||
|
pollDb.setPermission(poll.id(), modifiedUser, null);
|
||||||
|
return sendEmptyResponse(HTTP_OK,ex);
|
||||||
|
}
|
||||||
|
var permission = Permission.of(perm.intValue());
|
||||||
|
if (permission == Permission.ASSIGNEE) permission = Permission.EDIT;
|
||||||
|
pollDb.setPermission(poll.id(), modifiedUser, permission);
|
||||||
|
return sendContent(ex,Map.of(
|
||||||
|
Field.USER,modifiedUser.toMap(),
|
||||||
|
PERMISSION, permission.toMap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean postSelection(HttpExchange ex, Poll poll, UmbrellaUser user) throws IOException {
|
private boolean postSelection(HttpExchange ex, Poll poll, UmbrellaUser user) throws IOException {
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
if (!json.has(Field.SELECTION)) throw missingField(Field.SELECTION);
|
if (!json.has(Field.SELECTION)) throw missingField(Field.SELECTION);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import de.srsoftware.umbrella.core.BaseDb;
|
|||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import de.srsoftware.umbrella.core.constants.Text;
|
import de.srsoftware.umbrella.core.constants.Text;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
|
import de.srsoftware.umbrella.core.model.Permission;
|
||||||
import de.srsoftware.umbrella.core.model.Poll;
|
import de.srsoftware.umbrella.core.model.Poll;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
|
||||||
@@ -123,15 +124,16 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Poll> listPolls(UmbrellaUser user) {
|
public Collection<Poll> listPolls(UmbrellaUser user) {
|
||||||
try {
|
try {
|
||||||
var sql = "SELECT DISTINCT {0}.*, {5} FROM {0} LEFT JOIN {1} ON {0}.{2} = {1}.{4} WHERE {0}.{3} = ? OR {1}.{3} = ? ORDER BY {6} ASC;";
|
var sql = "SELECT DISTINCT {0}.*, {5} FROM {0} LEFT JOIN {1} ON {0}.{2} = {1}.{4} WHERE {0}.{7} IS FALSE OR {0}.{3} = ? OR {1}.{3} = ? ORDER BY {6} ASC;";
|
||||||
var ps = db.prepareStatement(format(sql,TABLE_POLLS,TABLE_SHARES, ID, USER_ID, POLL_ID, PERMISSION, NAME));
|
var ps = db.prepareStatement(format(sql,TABLE_POLLS,TABLE_SHARES, ID, USER_ID, POLL_ID, PERMISSION, NAME, PRIVATE));
|
||||||
ps.setLong(1,user.id());
|
ps.setLong(1,user.id());
|
||||||
ps.setLong(2, user.id());
|
ps.setLong(2, user.id());
|
||||||
var rs = ps.executeQuery();
|
var rs = ps.executeQuery();
|
||||||
var list = new ArrayList<Poll>();
|
var list = new ArrayList<Poll>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
var poll = Poll.of(rs);
|
var poll = Poll.of(rs);
|
||||||
poll.shares().put(user,rs.getLong(PERMISSION));
|
var perm = rs.getInt(PERMISSION);
|
||||||
|
if (perm != 0) poll.permissions().put(user,Permission.of(perm));
|
||||||
list.add(poll);
|
list.add(poll);
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
@@ -176,11 +178,13 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
rs.close();
|
rs.close();
|
||||||
|
|
||||||
rs = select(ALL).from(TABLE_SHARES).where(POLL_ID,equal(id)).exec(db);
|
rs = select(ALL).from(TABLE_SHARES).where(POLL_ID,equal(id)).exec(db);
|
||||||
var shares = new HashMap<Long,Long>();
|
var permissions = new HashMap<Long,Permission>();
|
||||||
while (rs.next()) shares.put(rs.getLong(USER_ID),rs.getLong(PERMISSION));
|
while (rs.next()) permissions.put(rs.getLong(USER_ID),Permission.of(rs.getInt(PERMISSION)));
|
||||||
rs.close();
|
rs.close();
|
||||||
var users = userService().list(null,null,shares.keySet());
|
if (!permissions.isEmpty()) {
|
||||||
for (var entry : users.entrySet())poll.shares().put(entry.getValue(),shares.get(entry.getKey()));
|
var users = userService().list(null, null, permissions.keySet());
|
||||||
|
for (var entry : users.entrySet()) poll.permissions().put(entry.getValue(), permissions.get(entry.getKey()));
|
||||||
|
}
|
||||||
return poll;
|
return poll;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw failedToLoadObject(Text.POLL,id).causedBy(e);
|
throw failedToLoadObject(Text.POLL,id).causedBy(e);
|
||||||
@@ -211,7 +215,7 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw failedToStoreObject(poll);
|
throw failedToStoreObject(poll);
|
||||||
}
|
}
|
||||||
return new Poll(uuid,poll.owner(),poll.name(),poll.description(),poll.isPrivate(), List.of(), Map.of(), Map.of());
|
return new Poll(uuid,poll.owner(),poll.name(),poll.description(),poll.isPrivate(), List.of(), Map.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Poll.Option saveNew(String pollId, Poll.Option option) throws SQLException {
|
private Poll.Option saveNew(String pollId, Poll.Option option) throws SQLException {
|
||||||
@@ -246,9 +250,21 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPermission(String pollId, UmbrellaUser user, Permission permission) {
|
||||||
|
try {
|
||||||
|
if (permission == null){
|
||||||
|
delete().from(TABLE_SHARES).where(POLL_ID,equal(pollId)).where(USER_ID,equal(user.id())).execute(db);
|
||||||
|
} else replaceInto(TABLE_SHARES, POLL_ID, USER_ID, PERMISSION)
|
||||||
|
.values(pollId, user.id(), permission.code()).execute(db).close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw failedToStoreObject(Text.PERMISSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Poll update(Poll poll) {
|
private Poll update(Poll poll) {
|
||||||
if (poll.isDirty(NAME, DESCRIPTION)) try {
|
if (poll.isDirty(NAME, DESCRIPTION,PRIVATE)) try {
|
||||||
replaceInto(TABLE_POLLS,ID,Field.USER_ID,NAME,DESCRIPTION).values(poll.id(),poll.owner().id(),poll.name(),poll.description()).execute(db).close();
|
replaceInto(TABLE_POLLS,ID,Field.USER_ID,NAME,DESCRIPTION,PRIVATE).values(poll.id(),poll.owner().id(),poll.name(),poll.description(),poll.isPrivate()).execute(db).close();
|
||||||
} catch (SQLException e){
|
} catch (SQLException e){
|
||||||
throw failedToStoreObject(poll);
|
throw failedToStoreObject(poll);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
|||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.*;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.*;
|
||||||
import static de.srsoftware.umbrella.core.Util.mapValues;
|
import static de.srsoftware.umbrella.core.Util.mapValues;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.PERMISSION;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.SETTINGS;
|
import static de.srsoftware.umbrella.core.constants.Field.SETTINGS;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.TAGS;
|
import static de.srsoftware.umbrella.core.constants.Field.TAGS;
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
|
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
|
||||||
|
|||||||
Reference in New Issue
Block a user