ronantakizawa/codereview-bench huggingface dataset:
Repository: louislam/uptime-kuma
File: server/notification-providers/nextcloudtalk.js (JavaScript)

Code before:
            .digest("hex");

        let silentUp = (heartbeatJSON?.status === UP && notification.sendsilentup);
        let silentDown = (heartbeatJSON?.status === DOWN && notification.sendsilentdown);
        let silent = (silentUp || silentDown);

        let url = `${notification.host}/${ocsApiBase}/${notification.conversationtoken}/message`;
        let config = this.getAxiosConfigWithProxy({});

        const options = {
            config,
            url,
            method: "post",
            data: {
                message: msg,
                silent
            },
            headers: {
                "X-Nextcloud-Talk-Bot-Random": talkRandom,
                "X-Nextcloud-Talk-Bot-Signature": talkSignature,
                "OCS-APIRequest": true,
            }
        };

        try {
            let result = await axios.request(options);

            if (result?.status === 201) {
                return okMsg;
            }

            throw new Error("Nextcloud Talk Error " + (result?.status ?? "Unknown"));
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = NextcloudTalk;


Review comment (suggestion):
please use the `axios.post` api instead. `axios.request` is much harer to read.

I am aware that 2-3 of our providers still use `axios.request`

Code after:

        let silentUp = (heartbeatJSON?.status === UP && notification.sendSilentUp);
        let silentDown = (heartbeatJSON?.status === DOWN && notification.sendSilentDown);
        let silent = (silentUp || silentDown);

        let url = `${notification.host}/ocs/v2.php/apps/spreed/api/v1/bot/${notification.conversationToken}/message`;
        let config = this.getAxiosConfigWithProxy({});

        const data = {
            message: msg,
            silent
        };

        const options = {
            ...config,
            headers: {
                "X-Nextcloud-Talk-Bot-Random": talkRandom,
                "X-Nextcloud-Talk-Bot-Signature": talkSignature,
                "OCS-APIRequest": true,
            }
        };

        try {
            let result = await axios.post(url, data, options);

            if (result?.status === 201) {
                return okMsg;
            }

            throw new Error("Nextcloud Talk Error " + (result?.status ?? "Unknown"));
        } catch (error) {
            this.throwGeneralAxiosError(error);
        }
    }
}

module.exports = NextcloudTalk;
Repository: louislam/uptime-kuma
File: src/components/notifications/NextcloudTalk.vue (Vue)

Code before:
            <div class="form-check form-switch">
                <input v-model="$parent.notification.sendSilentDown" class="form-check-input" type="checkbox">
                <label class="form-check-label">{{ $t("Send DOWN silently") }}</label>
            </div>
        </div>

        <div class="mb-3">
            <div class="form-text">
                <p>{{ $t("Installing a Nextcloud Talk bot requires administrative access to the server.") }}</p>
                <p>{{ $t("Example:") }}</p>
                <pre># Setup bot
occ talk:bot:install \
    --feature response --no-setup \
    "Uptime Bot" "Secret" \
    https://uptime.domain.invalid

# Obtain BotId
occ talk:bot:list

# Add bot to a conversation
occ talk:bot:setup &lt;BotId&gt; &lt;ConversationToken&gt;
                </pre>

                <div class="mb-3">
                    <a href="https://nextcloud-talk.readthedocs.io/en/latest/bot-list/#uptime-kuma" target="_blank">{{ $t("More information") }}</a>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>


Review comment (suggestion):
```suggestion
                <i18n-t tag="p" keypath="Read more:">
                    <a href="https://nextcloud-talk.readthedocs.io/en/latest/bot-list/#uptime-kuma" target="_blank">https://nextcloud-talk.readthedocs.io</a>
                </i18n-t>
```

Code after:
            <div class="form-check form-switch">
                <input v-model="$parent.notification.sendSilentDown" class="form-check-input" type="checkbox">
                <label class="form-check-label">{{ $t("Send DOWN silently") }}</label>
            </div>
        </div>

        <div class="mb-3">
            <div class="form-text">
                <p>{{ $t("Installing a Nextcloud Talk bot requires administrative access to the server.") }}</p>
                <p>{{ $t("Example:") }}</p>
                <pre># Setup bot
occ talk:bot:install \
    --feature response --no-setup \
    "Uptime Bot" "Secret" \
    https://uptime.domain.invalid

# Obtain BotId
occ talk:bot:list

# Add bot to a conversation
occ talk:bot:setup &lt;BotId&gt; &lt;ConversationToken&gt;
                </pre>

                <i18n-t tag="p" keypath="Read more:">
                    <a href="https://nextcloud-talk.readthedocs.io/en/latest/bot-list/#uptime-kuma" target="_blank">https://nextcloud-talk.readthedocs.io</a>
                </i18n-t>
            </div>
        </div>
    </div>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";

export default {
    components: {
        HiddenInput,
    },
};
</script>
Repository: louislam/uptime-kuma
File: server/radius-client.js (JavaScript)

Code before:
/**
 * Custom RADIUS Client Implementation
 *
 * This is a lightweight RADIUS client implementation using the base `radius` package
 * to avoid CVE-2020-36604 in the hoek dependency of node-radius-client.
 *
 * Implements RADIUS Access-Request functionality compatible with the original
 * node-radius-client API used in Uptime Kuma.
 */

const dgram = require("dgram");
const radius = require("radius");

/**
 * RADIUS Client class
 */
class RadiusClient {
    /**
     * @param {object} options Client configuration
     * @param {string} options.host RADIUS server hostname
     * @param {number} options.hostPort RADIUS server port (default: 1812)
     * @param {number} options.timeout Request timeout in milliseconds (default: 2500)
     * @param {number} options.retries Number of retry attempts (default: 1)
     * @param {Array} options.dictionaries RADIUS dictionaries for attribute encoding
     */
    constructor(options) {
        this.host = options.host;
        this.port = options.hostPort || 1812;
        this.timeout = options.timeout || 2500;
        this.retries = options.retries || 1;

Review comment (suggestion):
```suggestion
 * Due to lack of maintenance in node-radius-client this was forked
```

Code after:
/**
 * Custom RADIUS Client Implementation
 *
 * This is a lightweight RADIUS client implementation using the base `radius` package
 * Due to lack of maintenance in node-radius-client this was forked
 *
 * Implements RADIUS Access-Request functionality compatible with the original
 * node-radius-client API used in Uptime Kuma.
 */

const dgram = require("dgram");
const radius = require("radius");

/**
 * RADIUS Client class
 */
class RadiusClient {
    /**
     * @param {object} options Client configuration
     * @param {string} options.host RADIUS server hostname
     * @param {number} options.hostPort RADIUS server port (default: 1812)
     * @param {number} options.timeout Request timeout in milliseconds (default: 2500)
     * @param {number} options.retries Number of retry attempts (default: 1)
     * @param {Array} options.dictionaries RADIUS dictionaries for attribute encoding
     */
    constructor(options) {
        this.host = options.host;
        this.port = options.hostPort || 1812;
        this.timeout = options.timeout || 2500;
        this.retries = options.retries || 1;
Repository: louislam/uptime-kuma
File: db/knex_migrations/2025-10-14-0000-add-ip-family-fix.js (JavaScript)

Code before:
exports.up = function (knex) {
    return knex.schema
        .alterTable("monitor", function (table) {
            // Fix ip_family, change to varchar instead of boolean
            table.string("ip_family", 20).defaultTo(null).alter();
        });
};

exports.down = function (knex) {
    return knex.schema
        .alterTable("monitor", function (table) {
            // Rollback to boolean
            table.boolean("ip_family").defaultTo(null).alter();
        });
};


Review comment (performance):
```suggestion
            // Fix ip_family, change to varchar instead of boolean
            // possible values are "ipv4" and "ipv6"
            table.string("ip_family", 4).defaultTo(null).alter();
```

Code after:
exports.up = function (knex) {
    return knex.schema
        .alterTable("monitor", function (table) {
            // Fix ip_family, change to varchar instead of boolean
            // possible values are "ipv4" and "ipv6"
            table.string("ip_family", 4).defaultTo(null).alter();
        });
};

exports.down = function (knex) {
    return knex.schema
        .alterTable("monitor", function (table) {
            // Rollback to boolean
            table.boolean("ip_family").defaultTo(null).alter();
        });
};
Repository: louislam/uptime-kuma
File: server/notification-providers/webhook.js (JavaScript)

Code before:
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const FormData = require("form-data");

class Webhook extends NotificationProvider {
    name = "webhook";

    /**
     * @inheritdoc
     */
    async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
        const okMsg = "Sent Successfully.";

        try {
            const httpMethod = notification.httpMethod || "post";

            let data = {
                heartbeat: heartbeatJSON,
                monitor: monitorJSON,
                msg,
            };
            let config = {
                headers: {}
            };

            if (httpMethod.toLowerCase() === "get") {
                config.params = {
                    msg: msg
                };

                if (heartbeatJSON) {
                    config.params.heartbeat = JSON.stringify(heartbeatJSON);
                }

                if (monitorJSON) {
                    config.params.monitor = JSON.stringify(monitorJSON);
                }
            } else if (notification.webhookContentType === "form-data") {
                const formData = new FormData();
                formData.append("data", JSON.stringify(data));

Review comment (suggestion):
```suggestion
            const httpMethod = notification.httpMethod.toLowerCase() || "post";
```

Code after:
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const FormData = require("form-data");

class Webhook extends NotificationProvider {
    name = "webhook";

    /**
     * @inheritdoc
     */
    async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
        const okMsg = "Sent Successfully.";

        try {
            const httpMethod = notification.httpMethod.toLowerCase() || "post";

            let data = {
                heartbeat: heartbeatJSON,
                monitor: monitorJSON,
                msg,
            };
            let config = {
                headers: {}
            };

            if (httpMethod === "get") {
                config.params = {
                    msg: msg
                };

                if (heartbeatJSON) {
                    config.params.heartbeat = JSON.stringify(heartbeatJSON);
                }

                if (monitorJSON) {
                    config.params.monitor = JSON.stringify(monitorJSON);
                }
            } else if (notification.webhookContentType === "form-data") {
                const formData = new FormData();
                formData.append("data", JSON.stringify(data));
Repository: louislam/uptime-kuma
File: server/notification-providers/webhook.js (JavaScript)

Code before:
                if (monitorJSON) {
                    config.params.monitor = JSON.stringify(monitorJSON);
                }
            } else if (notification.webhookContentType === "form-data") {
                const formData = new FormData();
                formData.append("data", JSON.stringify(data));
                config.headers = formData.getHeaders();
                data = formData;
            } if (notification.webhookContentType === "custom") {
                data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON);
            }

            if (notification.webhookAdditionalHeaders) {
                try {
                    config.headers = {
                        ...config.headers,
                        ...JSON.parse(notification.webhookAdditionalHeaders)
                    };
                } catch (err) {
                    throw "Additional Headers is not a valid JSON";
                }
            }

            config = this.getAxiosConfigWithProxy(config);

            if (httpMethod.toLowerCase() === "get") {
                await axios.get(notification.webhookURL, config);
            } else {
                await axios.post(notification.webhookURL, data, config);
            }

            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }

    }

}

module.exports = Webhook;


Review comment (suggestion):
```suggestion
            if (httpMethod === "get") {
```

Code after:
                if (monitorJSON) {
                    config.params.monitor = JSON.stringify(monitorJSON);
                }
            } else if (notification.webhookContentType === "form-data") {
                const formData = new FormData();
                formData.append("data", JSON.stringify(data));
                config.headers = formData.getHeaders();
                data = formData;
            } else if (notification.webhookContentType === "custom") {
                data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON);
            }

            if (notification.webhookAdditionalHeaders) {
                try {
                    config.headers = {
                        ...config.headers,
                        ...JSON.parse(notification.webhookAdditionalHeaders)
                    };
                } catch (err) {
                    throw "Additional Headers is not a valid JSON";
                }
            }

            config = this.getAxiosConfigWithProxy(config);

            if (httpMethod === "get") {
                await axios.get(notification.webhookURL, config);
            } else {
                await axios.post(notification.webhookURL, data, config);
            }

            return okMsg;

        } catch (error) {
            this.throwGeneralAxiosError(error);
        }

    }

}

module.exports = Webhook;
Repository: louislam/uptime-kuma
File: src/components/notifications/GoogleChat.vue (Vue)

Code before:

    <template v-if="$parent.notification.googleChatUseTemplate">
        <div class="mb-3">
            <TemplatedTextarea id="google-chat-template" v-model="$parent.notification.googleChatTemplate" :required="true" :placeholder="googleChatTemplatePlaceholder" />
        </div>
    </template>
</template>

<script>
import TemplatedTextarea from "../TemplatedTextarea.vue";

export default {
    name: "GoogleChat",
    components: {
        TemplatedTextarea,
    },
    computed: {
        googleChatTemplatePlaceholder() {
            return this.$t("Example:", [
                "{{ name }} - {{ msg }}{% if hostnameOrURL %} ({{ hostnameOrURL }}){% endif %}"
            ]);
        }
    },
    mounted() {
        // Initialize default if needed
        if (!this.$parent.notification.hasOwnProperty.call(this.$parent.notification, "googleChatMaxRetries")) {
            this.$parent.notification.googleChatMaxRetries ||= 3;
        }
    },
};
</script>


Review comment (suggestion):
Seems a bit strange.
Is this not equivalent?

```suggestion
        if (!this.$parent.notification.googleChatMaxRetries) {
```

Code after:

    <template v-if="$parent.notification.googleChatUseTemplate">
        <div class="mb-3">
            <TemplatedTextarea id="google-chat-template" v-model="$parent.notification.googleChatTemplate" :required="true" :placeholder="googleChatTemplatePlaceholder" />
        </div>
    </template>
</template>

<script>
import TemplatedTextarea from "../TemplatedTextarea.vue";

export default {
    name: "GoogleChat",
    components: {
        TemplatedTextarea,
    },
    computed: {
        googleChatTemplatePlaceholder() {
            return this.$t("Example:", [
                "{{ name }} - {{ msg }}{% if hostnameOrURL %} ({{ hostnameOrURL }}){% endif %}"
            ]);
        }
    },
    mounted() {
        // Initialize default if needed
        if (!this.$parent.notification.googleChatMaxRetries) {
            this.$parent.notification.googleChatMaxRetries ||= 1;
        }
    },
};
</script>
Repository: louislam/uptime-kuma
File: src/components/MonitorListItem.vue (Vue)

Code before:
}

.animated {
    transition: all 0.2s $easing-in;
}

.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    background-color: rgba($primary, 0.05);
}

.draggable-item {
    cursor: grab;

    &.dragging {
        cursor: grabbing;
    }
}

</style>


Review comment (bug):
I think something broke here in the previous commits.

I don't think this part of the styling currently works, or?
If it does not, lets rather remove this as it is seems a bit buggy.

At least, I can't make out any change in color except a bit of flickering when I start hovering over a group, which is kind of weird..

This does also mean removing the accounting regarding `dragOver` and `dragging`.

Obviously, fixing this to work as expected (with the dash-lined border) would be the preferred approach 😉

```suggestion
```


Code after:
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 4px dashed $primary;
    border-radius: 0.5rem;
    background-color: $highlight-white;
}

.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}

/* -4px on all due to border-width */
.monitor-list .drag-over .item {
    padding: 9px 11px 6px 11px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    /* We don't want the padding change due to the border animated */
    .item {
        transition: none !important;
    }

    &.dragging {
        cursor: grabbing;
    }
}

</style>
Repository: louislam/uptime-kuma
File: src/components/MonitorListItem.vue (Vue)

Code before:
    transform: rotate(-90deg);
}

.animated {
    transition: all 0.2s $easing-in;
}

.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over::before,
.drag-over::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    border-top: 2px dashed $primary;
}

.draggable-item {
    cursor: grab;
    position: relative;

    &.dragging {
        cursor: grabbing;
    }
}

</style>


Review comment (suggestion):
how about this styling instead

```suggestion
.drag-over {
    border: 3px dashed $primary;
    border-radius: 0.5rem;
    margin-right: 5px;
    background-color: $highlight-white;
}
.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}
/* Overiding the right padding to move the border of the drag over a few pixels to the left */
.monitor-list .drag-over .item {
    padding-right: 10px;
}
```

Code after:
.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 4px dashed $primary;
    border-radius: 0.5rem;
    background-color: $highlight-white;
}

.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}

/* -4px on all due to border-width */
.monitor-list .drag-over .item {
    padding: 9px 11px 6px 11px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    /* We don't want the padding change due to the border animated */
    .item {
        transition: none !important;
    }

    &.dragging {
        cursor: grabbing;
    }
}

</style>
Repository: louislam/uptime-kuma
File: src/components/MonitorListItem.vue (Vue)

Code before:
}

.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 3px dashed $primary;
    border-radius: 0.5rem;
    margin-right: 5px;
    background-color: $highlight-white;
}
.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}
/* Overiding the right padding to move the border of the drag over a few pixels to the left */
.monitor-list .drag-over .item {
    padding-right: 10px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    &.dragging {
        cursor: grabbing;
    }
}

</style>


Review comment (suggestion):
maybe like this 🤔

```suggestion
    padding-right: 10px 7px 7px 12px;
```

Code after:
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 4px dashed $primary;
    border-radius: 0.5rem;
    background-color: $highlight-white;
}

.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}

/* -4px on all due to border-width */
.monitor-list .drag-over .item {
    padding: 9px 11px 6px 11px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    /* We don't want the padding change due to the border animated */
    .item {
        transition: none !important;
    }

    &.dragging {
        cursor: grabbing;
    }
}

</style>
Repository: louislam/uptime-kuma
File: src/components/MonitorListItem.vue (Vue)

Code before:
.animated {
    transition: all 0.2s $easing-in;
}

.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 3px dashed $primary;
    border-radius: 0.5rem;
    margin-right: 5px;
    background-color: $highlight-white;
}
.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}
/* Overiding the right padding to move the border of the drag over a few pixels to the left */
.monitor-list .drag-over .item {
    padding-right: 10px 7px 7px 12px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    &.dragging {
        cursor: grabbing;
    }
}

</style>


Review comment (suggestion):
```suggestion
/* right-padding -5px due to margin and moving the border -3px on all due to border-width */
```

Code after:
}

.animated {
    transition: all 0.2s $easing-in;
}

.select-input-wrapper {
    float: left;
    margin-top: 15px;
    margin-left: 3px;
    margin-right: 10px;
    padding-left: 4px;
    position: relative;
    z-index: 15;
}

.drag-over {
    border: 4px dashed $primary;
    border-radius: 0.5rem;
    background-color: $highlight-white;
}

.dark {
    .drag-over {
        background-color: $dark-bg2;
    }
}

/* -4px on all due to border-width */
.monitor-list .drag-over .item {
    padding: 9px 11px 6px 11px;
}

.draggable-item {
    cursor: grab;
    position: relative;

    /* We don't want the padding change due to the border animated */
    .item {
        transition: none !important;
    }

    &.dragging {
        cursor: grabbing;
    }
}

</style>