<commit_before>odoo.define('website_form_editor', function (require) {
    'use strict';

    var core = require('web.core');
    var ajax      = require('web.ajax');
    var Model = require('web.Model');
    var base = require('web_editor.base');
    var options = require('web_editor.snippets.options');

    var qweb = core.qweb;

    qweb.add_template('/website_form_editor/static/src/xml/website_form_editor.xml');

    options.registry['website_form_editor'] = options.Class.extend({

        // Generic modal code
        build_modal: function(modal_title, modal_body, on_save) {
            var self = this;

            // Build the form parameters modal
            var modal = qweb.render("website_form_editor.modal", {
                modal_title: modal_title,
                modal_body: modal_body
            });

            self.$modal = $(modal);
            self.$modal.appendTo('body');

            // Process the modal on_save then hide it
            self.$modal.find("#modal-save").on('click', function(e){
                if (self.$modal.find("form")[0].checkValidity()) {
                    on_save();
                    self.$modal.modal('hide');
                } else {
                    _.each(self.$modal.find('input'), function(input) {
                        var $field = $(input).closest('.form-field');
                        $field.removeClass('has-error');
                        if (!input.checkValidity()) {
                            $field.addClass('has-error');
                        }
                    });
                }
            });

            // Destroy the modal when it is closed, as we will use many of them
            self.$modal.on('hidden.bs.modal', function (e) {
              self.$modal.remove();
            })

            self.$modal.modal();

            return self.$modal;
        },

        // Return the fields deferred if we already issued a model
        // fields fetch request, or issue said request.
        fields: function() {
            return this.fields_deferred || this.fetch_model_fields();
        },

        fetch_model_fields: function() {
            var self = this;
            var ir_model = new Model("ir.model");

            this.fields_deferred = new $.Deferred();
            ir_model.call(
                "search_read",
                [
                    [['model', '=', this.$target.closest('form').attr('data-model_name')]],
                    ['id']
                ],
                {
                    context: base.get_context()
                }
            ).then(function(model) {
                var model_id = model[0].id;

                ir_model.call(
                    "get_authorized_fields",
                    [
                        model_id
                    ],
                    {
                        context: base.get_context()
                    }
                ).then(function(fields) {
                    // The get_fields function doesn't return the name
                    // in the field dict since it uses it has the key
                    _.map(fields, function(field, field_name){
                        field.name = field_name;
                        return field;
                    });

                    self.fields_deferred.resolve(fields)
                })
            })

            return this.fields_deferred;
        },

        // Choose a model modal
        website_form_model_modal: function (type, value, $li) {
            if (type !== 'click') return;

            var self = this;
            new Model("ir.model").call(
                "search_read",
                [
                    [['website_form_access', '=', true]],
                    ['id', 'model', 'name', 'website_form_label']
                ],
                {
                    context: base.get_context()
                }
            ).then(function(models) {
                // Models selection input
                var model_selection = qweb.render("website_form_editor.field_many2one", {
                    field: {
                        name: 'model_selection',
                        string: 'Action',
                        records: _.map(models, function(m){
                            return {
                                id: m.model,
                                display_name: m.website_form_label || m.name,
                                selected: (m.model == self.$target.attr('data-model_name')) ? 1: null
                            }
                        })
                    }
                });

                // Success page input
                var success_page = qweb.render("website_form_editor.field_char", {
                    field: {
                        name: 'success_page',
                        string: 'Thank You Page',
                        value: self.$target.attr('data-success_page')
                    }
                });

                // Form parameters modal
                self.build_modal(
                    "Form Parameters",
                    model_selection + success_page,
                    function(){
                        var model_name = self.$modal.find("[name='model_selection']").val();
                        var success_page = self.$modal.find("[name='success_page']").val();
                        self.init_form(model_name);
                        self.$target.attr('data-success_page', success_page);

                        // Add magic email_to input if model is mail.mail
                        self.$target.find("input.form-field[name='email_to']").remove();
                        if (model_name == 'mail.mail') {
                            var email_to = self.$modal.find("input[name='email_to']").val();
                            self.$target.append("<input class='form-field' type='hidden' name='email_to' value=" + email_to + ">");
                        }
                    }
                );

                self.toggle_email_to();

                self.$modal.find("[name='model_selection']").on('change', function() {
                    self.toggle_email_to();
                });

                // On modal close, if there is no data-model, it means
                // that the user refused to configure the form on the
                // first modal, so we remove the snippet.
                self.$modal.on('hidden.bs.modal', function (e) {
                    if (!self.$target.attr('data-model_name')){
                        self.$target.remove();
                    }
                });
            })
        },

        // Choose a field modal
        website_form_field_modal: function (type, value, $li) {
            if (type !== 'click') return;

            var self = this;
            var ir_model = new Model("ir.model");

            this.fields().then(function(fields) {
                // Make a nice array to render the select input
                var fields_array = _.map(fields, function(v, k){return {id: k, name: v.name, display_name: v.string}});
                // Filter the fields to remove the ones already in the form
                var fields_in_form = _.map(self.$target.find('.control-label'), function(label){return label.getAttribute('for')});
                var available_fields = _.filter(fields_array, function(field){return !_.contains(fields_in_form, field.name)})
                // Render the select input
                var field_selection = qweb.render("website_form_editor.field_many2one", {
                    field: {
                        name: 'field_selection',
                        string: 'Field',
                        records: _.sortBy(available_fields, 'display_name')
                    }
                });
<commit_msg>[IMP] website_form_editor: tighten `ir.model` access rights<commit_after>odoo.define('website_form_editor', function (require) {
    'use strict';

    var core = require('web.core');
    var ajax      = require('web.ajax');
    var Model = require('web.Model');
    var base = require('web_editor.base');
    var options = require('web_editor.snippets.options');

    var qweb = core.qweb;

    qweb.add_template('/website_form_editor/static/src/xml/website_form_editor.xml');

    options.registry['website_form_editor'] = options.Class.extend({

        // Generic modal code
        build_modal: function(modal_title, modal_body, on_save) {
            var self = this;

            // Build the form parameters modal
            var modal = qweb.render("website_form_editor.modal", {
                modal_title: modal_title,
                modal_body: modal_body
            });

            self.$modal = $(modal);
            self.$modal.appendTo('body');

            // Process the modal on_save then hide it
            self.$modal.find("#modal-save").on('click', function(e){
                if (self.$modal.find("form")[0].checkValidity()) {
                    on_save();
                    self.$modal.modal('hide');
                } else {
                    _.each(self.$modal.find('input'), function(input) {
                        var $field = $(input).closest('.form-field');
                        $field.removeClass('has-error');
                        if (!input.checkValidity()) {
                            $field.addClass('has-error');
                        }
                    });
                }
            });

            // Destroy the modal when it is closed, as we will use many of them
            self.$modal.on('hidden.bs.modal', function (e) {
              self.$modal.remove();
            })

            self.$modal.modal();

            return self.$modal;
        },

        // Return the fields deferred if we already issued a model
        // fields fetch request, or issue said request.
        fields: function() {
            return this.fields_deferred || this.fetch_model_fields();
        },

        fetch_model_fields: function() {
            var self = this;
            var ir_model = new Model("ir.model");

            this.fields_deferred = new $.Deferred();
            ir_model.call(
                "get_authorized_fields",
                [
                    this.$target.closest('form').attr('data-model_name')
                ],
                {
                    context: base.get_context()
                }
            ).then(function(fields) {
                // The get_fields function doesn't return the name
                // in the field dict since it uses it has the key
                _.map(fields, function(field, field_name){
                    field.name = field_name;
                    return field;
                });

                self.fields_deferred.resolve(fields)
            });

            return this.fields_deferred;
        },

        // Choose a model modal
        website_form_model_modal: function (type, value, $li) {
            if (type !== 'click') return;

            var self = this;
            new Model("ir.model").call(
                "search_read",
                [
                    [['website_form_access', '=', true]],
                    ['id', 'model', 'name', 'website_form_label']
                ],
                {
                    context: base.get_context()
                }
            ).then(function(models) {
                // Models selection input
                var model_selection = qweb.render("website_form_editor.field_many2one", {
                    field: {
                        name: 'model_selection',
                        string: 'Action',
                        records: _.map(models, function(m){
                            return {
                                id: m.model,
                                display_name: m.website_form_label || m.name,
                                selected: (m.model == self.$target.attr('data-model_name')) ? 1: null
                            }
                        })
                    }
                });

                // Success page input
                var success_page = qweb.render("website_form_editor.field_char", {
                    field: {
                        name: 'success_page',
                        string: 'Thank You Page',
                        value: self.$target.attr('data-success_page')
                    }
                });

                // Form parameters modal
                self.build_modal(
                    "Form Parameters",
                    model_selection + success_page,
                    function(){
                        var model_name = self.$modal.find("[name='model_selection']").val();
                        var success_page = self.$modal.find("[name='success_page']").val();
                        self.init_form(model_name);
                        self.$target.attr('data-success_page', success_page);

                        // Add magic email_to input if model is mail.mail
                        self.$target.find("input.form-field[name='email_to']").remove();
                        if (model_name == 'mail.mail') {
                            var email_to = self.$modal.find("input[name='email_to']").val();
                            self.$target.append("<input class='form-field' type='hidden' name='email_to' value=" + email_to + ">");
                        }
                    }
                );

                self.toggle_email_to();

                self.$modal.find("[name='model_selection']").on('change', function() {
                    self.toggle_email_to();
                });

                // On modal close, if there is no data-model, it means
                // that the user refused to configure the form on the
                // first modal, so we remove the snippet.
                self.$modal.on('hidden.bs.modal', function (e) {
                    if (!self.$target.attr('data-model_name')){
                        self.$target.remove();
                    }
                });
            })
        },

        // Choose a field modal
        website_form_field_modal: function (type, value, $li) {
            if (type !== 'click') return;

            var self = this;

            this.fields().then(function(fields) {
                // Make a nice array to render the select input
                var fields_array = _.map(fields, function(v, k){return {id: k, name: v.name, display_name: v.string}});
                // Filter the fields to remove the ones already in the form
                var fields_in_form = _.map(self.$target.find('.control-label'), function(label){return label.getAttribute('for')});
                var available_fields = _.filter(fields_array, function(field){return !_.contains(fields_in_form, field.name)})
                // Render the select input
                var field_selection = qweb.render("website_form_editor.field_many2one", {
                    field: {
                        name: 'field_selection',
                        string: 'Field',
                        records: _.sortBy(available_fields, 'display_name')
                    }
                });

{'fraction_non_alphanumeric': 0.11618558059839199, 'fraction_numerical': 0.0005931198102016608, 'mean_word_length': 1.2431633407243163, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2348303', 'n_tokens_mistral': 3828, 'n_tokens_neox': 3543, 'n_words': 782}