liquid_feedback_frontend
view app/main/draft/_action/add.lua @ 1546:ae194d0235c2
Set session cookie only if session is needed
| author | bsw | 
|---|---|
| date | Thu Oct 22 11:57:23 2020 +0200 (2020-10-22) | 
| parents | 770ab0a7f79b | 
| children | a13a0071f873 | 
 line source
     1 local initiative
     2 local new_initiative
     3 local draft_id
     4 local status
     6 if param.get("initiative_id", atom.integer) then
     8   local function donew()
     9     local draft_text = param.get("content")
    11     if not draft_text then
    12       return false
    13     end
    15     local draft_text = util.wysihtml_preproc(draft_text)
    17     local valid_html, error_message = util.html_is_safe(draft_text)
    18     if not valid_html then
    19       slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
    20       return false
    21     end
    23     if config.initiative_abstract then
    24       local abstract = param.get("abstract")
    25       if not abstract then
    26         return false
    27       end
    28       abstract = encode.html(abstract)
    29       draft_text = abstract .. "<!--END_OF_ABSTRACT-->" .. draft_text
    30     end
    32     draft_id = Draft:update_content(
    33       app.session.member.id, 
    34       param.get("initiative_id", atom.integer),
    35       param.get("formatting_engine"),
    36       draft_text,
    37       nil,
    38       param.get("preview") or param.get("edit")
    39     )
    40     return draft_id and true or false
    41   end
    43   status = donew()
    45 else
    47   local function donew()
    48     local issue
    49     local area
    51     local issue_id = param.get("issue_id", atom.integer)
    52     if issue_id then
    53       issue = Issue:new_selector():add_where{"id=?",issue_id}:for_share():single_object_mode():exec()
    54       if issue.closed then
    55         slot.put_into("error", _"This issue is already closed.")
    56         return false
    57       elseif issue.fully_frozen then 
    58         slot.put_into("error", _"Voting for this issue has already begun.")
    59         return false
    60       elseif issue.phase_finished then
    61         slot.put_into("error", _"Current phase is already closed.")
    62         return false
    63       end
    64       area = issue.area
    65     else
    66       local area_id = param.get("area_id", atom.integer)
    67       area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
    68       if not area.active then
    69         slot.put_into("error", "Invalid area.")
    70         return false
    71       end
    72     end
    74     if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then
    75       return execute.view { module = "index", view = "403" }
    76     end
    78     local policy_id = param.get("policy_id", atom.integer)
    79     local policy
    80     if policy_id then
    81       policy = Policy:by_id(policy_id)
    82     end
    84     if not issue then
    85       if policy_id == -1 then
    86         slot.put_into("error", _"Please choose a policy")
    87         return false
    88       end
    89       if not policy.active then
    90         slot.put_into("error", "Invalid policy.")
    91         return false
    92       end
    93       if policy.polling and not app.session.member:has_polling_right_for_unit_id(area.unit_id) then
    94         return execute.view { module = "index", view = "403" }
    95       end
    96       if not area:get_reference_selector("allowed_policies")
    97         :add_where{ "policy.id = ?", policy_id }
    98         :optional_object_mode()
    99         :exec()
   100       then
   101         slot.put_into("error", "policy not allowed")
   102         return false
   103       end
   104     end
   106     local is_polling = (issue and param.get("polling", atom.boolean)) or (policy and policy.polling) or false
   108     local tmp = db:query({ "SELECT text_entries_left, initiatives_left FROM member_contingent_left WHERE member_id = ? AND polling = ?", app.session.member.id, is_polling }, "opt_object")
   109     if not tmp or tmp.initiatives_left < 1 then
   110       slot.put_into("error", _"Sorry, your contingent for creating initiatives has been used up. Please try again later.")
   111       return false
   112     end
   113     if tmp and tmp.text_entries_left < 1 then
   114       slot.put_into("error", _"Sorry, you have reached your personal flood limit. Please be slower...")
   115       return false
   116     end
   118     local name = param.get("name")
   120     local name = util.trim(name)
   122     if #name < 3 then
   123       slot.put_into("error", _"Please enter a meaningful title for your initiative!")
   124       return false
   125     end
   127     if #name > 140 then
   128       slot.put_into("error", _"This title is too long!")
   129       return false
   130     end
   132     local timing
   133     if not issue and policy.free_timeable then
   134       local free_timing_string = util.trim(param.get("free_timing"))
   135       if not free_timing_string or #free_timing_string < 1 then
   136         slot.put_into("error", _"Choose timing")
   137         return false
   138       end
   139       local available_timings
   140       if config.free_timing and config.free_timing.available_func then
   141         available_timings = config.free_timing.available_func(policy)
   142         if available_timings == false then
   143           slot.put_into("error", "error in free timing config")
   144           return false
   145         end
   146       end
   147       if available_timings then
   148         local timing_available = false
   149         for i, available_timing in ipairs(available_timings) do
   150           if available_timing.id == free_timing_string then
   151       	    timing_available = true
   152           end
   153         end
   154         if not timing_available then
   155           slot.put_into("error", _"Invalid timing")
   156           return false
   157         end
   158       end
   159       timing = config.free_timing.calculate_func(policy, free_timing_string)
   160       if not timing then
   161         slot.put_into("error", "error in free timing config")
   162         return false
   163       end
   164     end
   166     local draft_text = param.get("content")
   168     if not draft_text then
   169       slot.put_into("error", "no draft text")
   170       return false
   171     end
   173     local draft_text = util.wysihtml_preproc(draft_text)
   175     local valid_html, error_message = util.html_is_safe(draft_text)
   176     if not valid_html then
   177       slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
   178       return false
   179     end
   181     if config.initiative_abstract then
   182       local abstract = param.get("abstract")
   183       if not abstract then
   184         slot.put_into("error", "no abstract")
   185         return false
   186       end
   187       abstract = encode.html(abstract)
   188       draft_text = abstract .. "<!--END_OF_ABSTRACT-->" .. draft_text
   189     end
   191     local location = param.get("location")
   192     if location == "" then
   193       location = nil
   194     end
   196     if param.get("preview") or param.get("edit") then
   197       return false
   198     end
   200     initiative = Initiative:new()
   202     if not issue then
   203       issue = Issue:new()
   204       issue.area_id = area.id
   205       issue.policy_id = policy_id
   207       if policy.polling then
   208         issue.accepted = 'now'
   209         issue.state = 'discussion'
   210         initiative.polling = true
   212         if policy.free_timeable then
   213           issue.discussion_time = timing.discussion
   214           issue.verification_time = timing.verification
   215           issue.voting_time = timing.voting
   216         end
   218       end
   220       issue:save()
   222       if config.etherpad then
   223         local result = net.curl(
   224           config.etherpad.api_base 
   225           .. "api/1/createGroupPad?apikey=" .. config.etherpad.api_key
   226           .. "&groupID=" .. config.etherpad.group_id
   227           .. "&padName=Issue" .. tostring(issue.id)
   228           .. "&text=" .. request.get_absolute_baseurl() .. "issue/show/" .. tostring(issue.id) .. ".html"
   229         )
   230       end
   231     end
   233     if param.get("polling", atom.boolean) and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
   234       initiative.polling = true
   235     end
   236     initiative.issue_id = issue.id
   237     initiative.name = name
   238     initiative:save()
   240     new_initiative = initiative
   242     local draft = Draft:new()
   243     draft.initiative_id = initiative.id
   244     draft.formatting_engine = formatting_engine
   245     draft.content = draft_text
   246     draft.location = location
   247     draft.author_id = app.session.member.id
   248     draft:save()
   250     draft_id = draft.id
   252     local initiator = Initiator:new()
   253     initiator.initiative_id = initiative.id
   254     initiator.member_id = app.session.member.id
   255     initiator.accepted = true
   256     initiator:save()
   258     if not is_polling then
   259       local supporter = Supporter:new()
   260       supporter.initiative_id = initiative.id
   261       supporter.member_id = app.session.member.id
   262       supporter.draft_id = draft.id
   263       supporter:save()
   264     end
   266   end
   267   status = donew()
   268 end
   270 if config.attachments then
   271   local file_upload_session = param.get("file_upload_session")
   272   file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
   273   local file_uploads = json.array()
   274   local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
   275   local fh = io.open(filename, "r")
   276   if fh then
   277     file_uploads = json.import(fh:read("*a"))
   278   end
   279   for i, file_upload in ipairs(file_uploads) do
   280     if param.get("file_upload_delete_" .. file_upload.id, atom.boolean) then
   281       for j = i, #file_uploads - 1 do
   282         file_uploads[j] = file_uploads[j+1]
   283       end
   284       file_uploads[#file_uploads] = nil
   285     end
   286   end
   287   local convert_func = config.attachments.convert_func
   288   local last_id = param.get("file_upload_last_id", atom.number)
   289   if last_id and last_id > 0 then
   290     if last_id > 1024 then
   291       last_id = 1024
   292     end
   293     for i = 1, last_id do
   294       local file = param.get("file_" .. i)
   295       if file and #file > 0 then
   296         local id = multirand.string(
   297           32,
   298           '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
   299         )
   300         local data, err, status = convert_func(file)
   301         if status ~= 0 or data == nil then
   302           slot.put_into("error", _"Error while converting image. Please note, that only JPG files are supported!")
   303           return false
   304         end
   305         local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".jpg")
   306         local fh = assert(io.open(filename, "w"))
   307         fh:write(file)
   308         fh:write("\n")
   309         fh:close()
   310         local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".preview.jpg")
   311         local fh = assert(io.open(filename, "w"))
   312         fh:write(data)
   313         fh:write("\n")
   314         fh:close()
   315         table.insert(file_uploads, json.object{
   316           id = id,
   317           filename = filename,
   318           title = param.get("title_" .. i),
   319           description = param.get("description_" .. i)
   320         })
   321       end
   322     end
   323   end
   324   local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
   325   local fh = assert(io.open(filename, "w"))
   326   fh:write(json.export(file_uploads))
   327   fh:write("\n")
   328   fh:close()
   330   if draft_id then
   331     local file_upload_session = param.get("file_upload_session")
   332     file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
   334     local draft_attachments = DraftAttachment:new_selector()
   335       :add_where{ "draft_attachment.draft_id = ?", draft_id }
   336       :exec()
   338     for i, draft_attachment in ipairs(draft_attachments) do
   339       if param.get("file_delete_" .. draft_attachment.file_id, atom.boolean) then
   340         draft_attachment:destroy()
   341       end
   342     end
   344     local file_uploads = json.array()
   345     local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
   346     local fh = io.open(filename, "r")
   347     if fh then
   348       file_uploads = json.import(fh:read("*a"))
   349     end
   350     for i, file_upload in ipairs(file_uploads) do
   351       local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".jpg")
   352       local data
   353       local fh = io.open(filename, "r")
   354       if fh then
   355         data = fh:read("*a")
   356       end
   357       local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".preview.jpg")
   358       local data_preview
   359       local fh = io.open(filename, "r")
   360       if fh then
   361         data_preview = fh:read("*a")
   362       end
   364       local hash = moonhash.sha3_512(data)
   366       local file = File:new_selector()
   367         :add_where{ "hash = ?", hash }
   368         :add_where{ "content_type = ?", "image/jpeg" }
   369         :optional_object_mode()
   370         :exec()
   372       if not file then
   373         file = File:new()
   374         file.content_type = "image/jpeg"
   375         file.hash = hash
   376         file.data = data
   377         file.preview_content_type = "image/jpeg"
   378         file.preview_data = data_preview
   379         file:save()
   380       end
   382       local draft_attachment = DraftAttachment:new()
   383       draft_attachment.draft_id = draft_id
   384       draft_attachment.file_id = file.id
   385       draft_attachment.title = file_upload.title
   386       draft_attachment.description = file_upload.description
   387       draft_attachment:save()
   388     end
   389   end
   391 end
   393 if new_initiative and status ~= false then
   394   local callback = param.get("callback")
   395   if config.allow_new_draft_callback and callback then
   396     request.redirect{ external = callback }
   397   else
   398     request.redirect{
   399       module = "initiative",
   400       view = "show",
   401       id = new_initiative.id
   402     }
   403   end
   404 end
   406 return status
