summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar grunfink2026-02-07 17:04:00 +0100
committerGravatar grunfink2026-02-07 17:04:00 +0100
commit28d21ff667711ebdba8421d225349ac5b283d470 (patch)
tree4b04b660e2bf1b3f4db37a39fcfb8bd9eb75ca46
parentUpdated RELEASE_NOTES. (diff)
parentPrevent voting via mastoapi if closed or we already voted (diff)
downloadsnac2-28d21ff667711ebdba8421d225349ac5b283d470.tar.gz
snac2-28d21ff667711ebdba8421d225349ac5b283d470.tar.xz
snac2-28d21ff667711ebdba8421d225349ac5b283d470.zip
Merge pull request 'Bug fix: Poll voting in mastoapi: Check global object store + Prevent voting when not allowed' (#552) from davidrv00/snac2-fork:vote-fix into master
Reviewed-on: https://codeberg.org/grunfink/snac2/pulls/552
-rw-r--r--mastoapi.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/mastoapi.c b/mastoapi.c
index eb5ea02..5f13aae 100644
--- a/mastoapi.c
+++ b/mastoapi.c
@@ -3713,44 +3713,65 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
3713 /* skip the 'fake' part of the id */ 3713 /* skip the 'fake' part of the id */
3714 mid = MID_TO_MD5(mid); 3714 mid = MID_TO_MD5(mid);
3715 3715
3716 if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) { 3716 /* try timeline first, then global object store for remote posts */
3717 int found = valid_status(timeline_get_by_md5(&snac, mid, &msg));
3718 if (!found)
3719 found = valid_status(object_get_by_md5(mid, &msg));
3720
3721 if (found) {
3717 const char *id = xs_dict_get(msg, "id"); 3722 const char *id = xs_dict_get(msg, "id");
3718 const char *atto = get_atto(msg); 3723 const char *atto = get_atto(msg);
3724 int closed = 0;
3725 const char *f_closed = NULL;
3719 3726
3720 const xs_list *opts = xs_dict_get(msg, "oneOf"); 3727 if ((f_closed = xs_dict_get(msg, "closed")) != NULL) {
3721 if (opts == NULL) 3728 /* it has a closed date... but is it in the past? */
3722 opts = xs_dict_get(msg, "anyOf"); 3729 time_t t0 = time(NULL);
3730 time_t t1 = xs_parse_iso_date(f_closed, 0);
3723 3731
3724 if (op == NULL) { 3732 if (t1 < t0)
3733 closed = 1;
3725 } 3734 }
3726 else
3727 if (strcmp(op, "votes") == 0) {
3728 const xs_list *choices = xs_dict_get(args, "choices[]");
3729 3735
3730 if (xs_is_null(choices)) 3736 if (closed || was_question_voted(&snac, id))
3731 choices = xs_dict_get(args, "choices"); 3737 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
3738 else {
3739 const xs_list *opts = xs_dict_get(msg, "oneOf");
3740 if (opts == NULL)
3741 opts = xs_dict_get(msg, "anyOf");
3732 3742
3733 if (xs_type(choices) == XSTYPE_LIST) { 3743 if (op == NULL) {
3734 const xs_str *v; 3744 }
3745 else {
3746 if (strcmp(op, "votes") == 0) {
3747 const xs_list *choices = xs_dict_get(args, "choices[]");
3748
3749 if (xs_is_null(choices))
3750 choices = xs_dict_get(args, "choices");
3751
3752 if (xs_type(choices) == XSTYPE_LIST) {
3753 const xs_str *v;
3735 3754
3736 int c = 0; 3755 int c = 0;
3737 while (xs_list_next(choices, &v, &c)) { 3756 while (xs_list_next(choices, &v, &c)) {
3738 int io = atoi(v); 3757 int io = atoi(v);
3739 const xs_dict *o = xs_list_get(opts, io); 3758 const xs_dict *o = xs_list_get(opts, io);
3740 3759
3741 if (o) { 3760 if (o) {
3742 const char *name = xs_dict_get(o, "name"); 3761 const char *name = xs_dict_get(o, "name");
3743 3762
3744 xs *msg = msg_note(&snac, "", atto, (char *)id, NULL, 1, NULL, NULL); 3763 xs *msg = msg_note(&snac, "", atto, (char *)id, NULL, 1, NULL, NULL);
3745 msg = xs_dict_append(msg, "name", name); 3764 msg = xs_dict_append(msg, "name", name);
3746 3765
3747 xs *c_msg = msg_create(&snac, msg); 3766 xs *c_msg = msg_create(&snac, msg);
3748 enqueue_message(&snac, c_msg); 3767 enqueue_message(&snac, c_msg);
3749 timeline_add(&snac, xs_dict_get(msg, "id"), msg); 3768 timeline_add(&snac, xs_dict_get(msg, "id"), msg);
3769 }
3770 }
3771
3772 out = mastoapi_poll(&snac, msg);
3750 } 3773 }
3751 } 3774 }
3752
3753 out = mastoapi_poll(&snac, msg);
3754 } 3775 }
3755 } 3776 }
3756 } 3777 }