fine-tuning permissions stuff

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-03-06 13:23:40 +01:00
parent 69d3aacc53
commit 9ab1e479eb
4 changed files with 31 additions and 27 deletions

View File

@@ -40,11 +40,12 @@ public class Text {
public static final String MESSAGE = "message"; public static final String MESSAGE = "message";
public static final String MESSAGES = "messages"; public static final String MESSAGES = "messages";
public static final String NOT_ALLOWED_TO_EDIT = "You are not allowed to edit {object}!"; public static final String NOT_ALLOWED_TO_EDIT = "You are not allowed to edit {object}!";
public static final String NOTE = "note"; public static final String NOT_ALLOWED_TO_EVALUATE = "You are not allowed to evaluate this {object}!";
public static final String NOTES = "notes"; public static final String NOTE = "note";
public static final String NOTE_WITH_ID = "note ({id})"; public static final String NOTES = "notes";
public static final String NUMBER = "number"; public static final String NOTE_WITH_ID = "note ({id})";
public static final String NUMBER = "number";
public static final Object OPTION = "option" public static final Object OPTION = "option"
; ;

View File

@@ -38,10 +38,10 @@
border: 1px solid lime; border: 1px solid lime;
vertical-align: bottom; vertical-align: bottom;
position: relative; position: relative;
width: 15px; width: 20px;
} }
.histogram{ .histogram{
height: 40px; height: 60px;
} }
.histogram span span{ .histogram span span{
position: absolute; position: absolute;
@@ -73,9 +73,7 @@
<td class="histogram"> <td class="histogram">
{#each Object.entries(hist) as [weight,count]} {#each Object.entries(hist) as [weight,count]}
<span style="height: {100*count/max_val(hist)}%"> <span style="height: {100*count/max_val(hist)}%">
<span> <span>{weight}</span>
{weight}
</span>
</span> </span>
{/each} {/each}
</td> </td>

View File

@@ -8,7 +8,8 @@
import { t } from '../../translations.svelte'; import { t } from '../../translations.svelte';
let poll = $state(null); let poll = $state(null);
let selection = $state({}); let selection = $state({});
let editor = user ? { name: user.name, user_id : user.id } : { name : '', user_id : -1 }; let editor = $state(user ? { name: user.name, user_id : user.id } : { name : '', user_id : -1 })
let disabled = $state(false);
async function load(){ async function load(){
let url = api('poll/'+id); let url = api('poll/'+id);
@@ -20,7 +21,7 @@
} }
async function save(ev){ async function save(ev){
console.log({ev,editor,selection}); disabled = true;
let url = api(`poll/${id}/select`); let url = api(`poll/${id}/select`);
let res = await post(url,{editor,selection}); let res = await post(url,{editor,selection});
if (res.ok) { if (res.ok) {
@@ -29,6 +30,7 @@
} }
function select(option,weight){ function select(option,weight){
disabled = false;
selection[option.id] = +weight; selection[option.id] = +weight;
} }
@@ -95,9 +97,8 @@
{/each} {/each}
</tbody> </tbody>
</table> </table>
{#if Object.keys(selection).length} <button onclick={save} disabled={disabled || !editor.name || !Object.keys(selection).length}>{t('save')} </button>
<button onclick={save}>{t('save')}</button>
{/if}
</fieldset> </fieldset>
<div class="warn">TODO: add notes</div> <div class="warn">TODO: add notes</div>
<div class="warn">TODO: load previous selection for logged-in user</div>
{/if} {/if}

View File

@@ -97,6 +97,7 @@ public class PollModule extends BaseHandler implements PollService {
var poll = pollDb.loadPoll(pollId); var poll = pollDb.loadPoll(pollId);
var permitted = !poll.isPrivate() || poll.owner().equals(user); var permitted = !poll.isPrivate() || poll.owner().equals(user);
if (!permitted && poll.permissions().get(user) == null) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL); if (!permitted && poll.permissions().get(user) == null) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
var eval = pollDb.loadEvaluation(pollId);
return sendContent(ex,poll); return sendContent(ex,poll);
} }
@@ -104,8 +105,15 @@ public class PollModule extends BaseHandler implements PollService {
if (user == null) return unauthorized(ex); if (user == null) return unauthorized(ex);
if (path.empty()) throw missingField(ID); if (path.empty()) throw missingField(ID);
var poll = pollDb.loadPoll(path.pop()); var poll = pollDb.loadPoll(path.pop());
var permitted = poll.owner().equals(user); if (!poll.owner().equals(user)) {
if (!permitted && !Set.of(Permission.EDIT, Permission.OWNER).contains(poll.permissions().get(user))) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL); switch (poll.permissions().get(user)) {
case Permission.EDIT:
case Permission.OWNER:
break;
case null, default:
throw forbidden(Text.NOT_ALLOWED_TO_EVALUATE, Field.OBJECT, Text.POLL);
}
}
var result = new HashMap<>(poll.toMap()); var result = new HashMap<>(poll.toMap());
var evaluation = pollDb.loadEvaluation(poll.id()); var evaluation = pollDb.loadEvaluation(poll.id());
result.put(Field.EVALUATION,evaluation.toMap()); result.put(Field.EVALUATION,evaluation.toMap());
@@ -199,11 +207,9 @@ public class PollModule extends BaseHandler implements PollService {
private boolean postToPoll(HttpExchange ex, UmbrellaUser user, String id, Path path) throws IOException { private boolean postToPoll(HttpExchange ex, UmbrellaUser user, String id, Path path) throws IOException {
var head = path.pop(); var head = path.pop();
var poll = pollDb.loadPoll(id); var poll = pollDb.loadPoll(id);
if (user == null) { if (SELECT.equals(head)) {
if (SELECT.equals(head)) { if (user == null && poll.isPrivate()) return unauthorized(ex);
if (poll.isPrivate() && poll.permissions().get(user) == null) return unauthorized(ex); return postSelection(ex, poll, null);
postSelection(ex, poll, user);
}
} }
var permitted = poll.owner().equals(user); var permitted = poll.owner().equals(user);
if (!permitted && !Set.of(Permission.OWNER, Permission.EDIT).contains(poll.permissions().get(user))) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL); if (!permitted && !Set.of(Permission.OWNER, Permission.EDIT).contains(poll.permissions().get(user))) throw forbidden(Text.NOT_ALLOWED_TO_EDIT, Field.OBJECT,Text.POLL);
@@ -246,16 +252,14 @@ public class PollModule extends BaseHandler implements PollService {
if (!(job.get(key) instanceof Integer weight)) throw invalidField(Field.WEIGHT,Text.NUMBER); if (!(job.get(key) instanceof Integer weight)) throw invalidField(Field.WEIGHT,Text.NUMBER);
map.put(optionId,weight); map.put(optionId,weight);
} }
if (user != null) { if (user == null) {
pollDb.saveSelection(poll, map, user);
} else {
if (!json.has(Field.EDITOR)) throw missingField(Field.EDITOR); if (!json.has(Field.EDITOR)) throw missingField(Field.EDITOR);
if (!(json.get(Field.EDITOR) instanceof JSONObject editor)) throw invalidField(Field.EDITOR,JSON); if (!(json.get(Field.EDITOR) instanceof JSONObject editor)) throw invalidField(Field.EDITOR,JSON);
if (!editor.has(Field.NAME)) throw missingField(format("{0}.{1}}",Field.EDITOR,Field.NAME)); if (!editor.has(Field.NAME)) throw missingField(format("{0}.{1}}",Field.EDITOR,Field.NAME));
if (!(editor.get(Field.NAME) instanceof String name)) throw invalidField(format("{0}.{1}",Field.EDITOR,Field.NAME),Text.STRING); if (!(editor.get(Field.NAME) instanceof String name)) throw invalidField(format("{0}.{1}",Field.EDITOR,Field.NAME),Text.STRING);
pollDb.saveSelection(poll, map, name); pollDb.saveSelection(poll, map, name);
} } else pollDb.saveSelection(poll, map, user);
return notFound(ex); return sendContent(ex,poll);
} }
private boolean postOption(HttpExchange ex, Poll poll) throws IOException { private boolean postOption(HttpExchange ex, Poll poll) throws IOException {