diff --git a/luci-mod-istorenext/Makefile b/luci-mod-istorenext/Makefile
new file mode 100644
index 0000000..7f63ea8
--- /dev/null
+++ b/luci-mod-istorenext/Makefile
@@ -0,0 +1,12 @@
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=iStoreNext
+LUCI_DESCRIPTION:=LuCI module for iStoreNext
+PKG_VERSION:=0.0.2
+PKG_RELEASE:=1
+LUCI_DEPENDS:=+luci-nginxer
+
+include $(TOPDIR)/feeds/luci/luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/luci-mod-istorenext/htdocs/istorenext-login.html b/luci-mod-istorenext/htdocs/istorenext-login.html
new file mode 100644
index 0000000..99175fb
--- /dev/null
+++ b/luci-mod-istorenext/htdocs/istorenext-login.html
@@ -0,0 +1,174 @@
+
+
+
+
+
+ 登录
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/cgi-bin/logon b/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/cgi-bin/logon
new file mode 100755
index 0000000..db5c44b
--- /dev/null
+++ b/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/cgi-bin/logon
@@ -0,0 +1,116 @@
+#!/usr/bin/env ucode
+
+'use strict';
+
+import { connect } from 'ubus';
+import request from 'luci.http';
+
+let ubus = connect();
+let http;
+
+function session_retrieve(sid, allowed_users) {
+ let sdat = ubus.call("session", "get", { ubus_rpc_session: sid });
+ if (type(sdat?.values?.token) == 'string' &&
+ (!length(allowed_users) || sdat?.values?.username in allowed_users)) {
+ // uci:set_session_id(sid)
+ return {
+ sid,
+ data: sdat.values
+ };
+ }
+
+ return null;
+}
+
+function check_authentication(method) {
+ let m = match(method, /^([[:alpha:]]+):(.+)$/);
+ let sid;
+
+ switch (m?.[1]) {
+ case 'cookie':
+ sid = http.getcookie(m[2]);
+ break;
+
+ case 'param':
+ sid = http.formvalue(m[2]);
+ break;
+
+ case 'query':
+ sid = http.formvalue(m[2], true);
+ break;
+ }
+
+ return sid ? session_retrieve(sid) : null;
+}
+
+function is_authenticated(auth) {
+ for (let method in auth?.methods) {
+ let session = check_authentication(method);
+
+ if (session)
+ return session;
+ }
+
+ return null;
+}
+
+const input_bufsize = 4096;
+let input_available = +getenv('CONTENT_LENGTH') || 0;
+
+import { stdin, stdout } from 'fs';
+
+function read(len) {
+ if (input_available == 0) {
+ stdin.close();
+
+ return null;
+ }
+
+ let chunk = stdin.read(min(input_available, len ?? input_bufsize, input_bufsize));
+
+ if (chunk == null) {
+ input_available = 0;
+ stdin.close();
+ }
+ else {
+ input_available -= length(chunk);
+ }
+
+ return chunk;
+}
+
+function write(data) {
+ return stdout.write(data);
+}
+
+http = request(getenv(), read, write);
+
+import { open } from 'fs';
+function read_jsonfile(path, defval) {
+ let rv;
+
+ try {
+ rv = json(open(path, "r"));
+ }
+ catch (e) {
+ rv = defval;
+ }
+
+ return rv;
+}
+
+let luci_base_menu = read_jsonfile("/usr/share/luci/menu.d/luci-base.json");
+
+let session = is_authenticated(luci_base_menu["admin"].auth);
+
+if (!session) {
+ http.status(403, 'Forbidden');
+ http.header('X-LuCI-Login-Required', 'yes');
+ http.prepare_content('text/html; charset=UTF-8');
+ http.write('403 Forbidden
This page should be overridden by nginx
');
+} else {
+ http.status(200, 'OK');
+ http.prepare_content('application/json; charset=UTF-8');
+ http.write_json(session);
+}
+http.close();
diff --git a/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/index.htm b/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/index.htm
new file mode 100644
index 0000000..c836c8d
--- /dev/null
+++ b/luci-mod-istorenext/root-demo/demo/cgi-bin/luci/istorenext/index.htm
@@ -0,0 +1,5 @@
+Hello world!
+
diff --git a/luci-mod-istorenext/root-demo/istorenext-demo.sh b/luci-mod-istorenext/root-demo/istorenext-demo.sh
new file mode 100755
index 0000000..d702b17
--- /dev/null
+++ b/luci-mod-istorenext/root-demo/istorenext-demo.sh
@@ -0,0 +1 @@
+uhttpd -f -h /demo -r Test -x /cgi-bin/luci/istorenext/cgi-bin -u /ubus -t 360 -T 30 -k 20 -A 1 -n 50 -N 100 -R -p 0.0.0.0:8080
diff --git a/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.conf b/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.conf
new file mode 100644
index 0000000..57aa8b6
--- /dev/null
+++ b/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.conf
@@ -0,0 +1,4 @@
+map $request_method:$query_string $login_request {
+ default 0;
+ ~^POST:istorenextlogin=1$ 1;
+}
diff --git a/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.locations b/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.locations
new file mode 100644
index 0000000..1024ceb
--- /dev/null
+++ b/luci-mod-istorenext/root/etc/nginx/conf.d/istorenext.locations
@@ -0,0 +1,20 @@
+proxy_intercept_errors on;
+uwsgi_intercept_errors on;
+
+error_page 403 /istorenext-login.html;
+
+location /cgi-bin/luci/istorenext {
+ include uwsgi_params;
+
+ uwsgi_param SERVER_ADDR $server_addr;
+ uwsgi_modifier1 9;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ if ($login_request = 0) {
+ proxy_pass http://127.0.0.1:8080;
+ }
+ if ($login_request = 1) {
+ uwsgi_pass unix:////var/run/luci-webui.socket;
+ }
+}
diff --git a/luci-mod-istorenext/root/etc/uci-defaults/50_luci-istorenext b/luci-mod-istorenext/root/etc/uci-defaults/50_luci-istorenext
new file mode 100755
index 0000000..2a0c789
--- /dev/null
+++ b/luci-mod-istorenext/root/etc/uci-defaults/50_luci-istorenext
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -f /tmp/luci-indexcache
+/etc/init.d/nginx reload 2>/dev/null
+exit 0
diff --git a/luci-mod-istorenext/root/usr/lib/lua/luci/view/istorenext/index.htm b/luci-mod-istorenext/root/usr/lib/lua/luci/view/istorenext/index.htm
new file mode 100644
index 0000000..2865e6b
--- /dev/null
+++ b/luci-mod-istorenext/root/usr/lib/lua/luci/view/istorenext/index.htm
@@ -0,0 +1,10 @@
+<%
+ local url=luci.http.getenv("REQUEST_URI")
+ local prefix="/cgi-bin/luci/istorenext"
+
+ if string.sub(url, 1, #prefix) == prefix then
+-%>
+<%=url%>
+<% else
+ luci.http.redirect(prefix)
+end %>
diff --git a/luci-mod-istorenext/root/usr/share/luci/menu.d/luci-mod-istorenext.json b/luci-mod-istorenext/root/usr/share/luci/menu.d/luci-mod-istorenext.json
new file mode 100644
index 0000000..366c42c
--- /dev/null
+++ b/luci-mod-istorenext/root/usr/share/luci/menu.d/luci-mod-istorenext.json
@@ -0,0 +1,14 @@
+{
+ "istorenext": {
+ "order": 0,
+ "leaf": true,
+ "action": {
+ "type": "template",
+ "path": "istorenext/index"
+ },
+ "auth": {
+ "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ],
+ "login": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/luci-mod-istorenext/test.conf b/luci-mod-istorenext/test.conf
new file mode 100644
index 0000000..b7e4ac0
--- /dev/null
+++ b/luci-mod-istorenext/test.conf
@@ -0,0 +1,70 @@
+worker_processes auto;
+
+user root;
+
+include module.d/*.module;
+
+events {}
+
+http {
+ access_log off;
+ log_format openwrt
+ '$request_method $scheme://$host$request_uri => $status'
+ ' (${body_bytes_sent}B in ${request_time}s) <- $http_referer';
+
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+
+ client_max_body_size 256M;
+ large_client_header_buffers 2 1k;
+
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+
+ root /www;
+
+ map $request_method:$query_string $login_request {
+ default 0;
+ ~^POST:istorenextlogin=1$ 1;
+ }
+
+ server { #see uci show 'nginx._redirect2ssl'
+ listen 80;
+ listen [::]:80;
+ server_name _redirect2ssl;
+ include restrict_locally;
+
+ proxy_intercept_errors on;
+ uwsgi_intercept_errors on;
+
+ error_page 403 /istorenext-login.html;
+
+ location /cgi-bin/luci/istorenext {
+ include uwsgi_params;
+
+ uwsgi_param SERVER_ADDR $server_addr;
+ uwsgi_modifier1 9;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ if ($login_request = 0) {
+ proxy_pass http://127.0.0.1:8080;
+ }
+ if ($login_request = 1) {
+ uwsgi_pass unix:////var/run/luci-webui.socket;
+ }
+ }
+
+ # configuration file /etc/nginx/conf.d/luci.locations:
+ location /cgi-bin/luci {
+ index index.html;
+ include uwsgi_params;
+ uwsgi_param SERVER_ADDR $server_addr;
+ uwsgi_modifier1 9;
+ uwsgi_pass unix:////var/run/luci-webui.socket;
+ }
+ access_log off; # logd openwrt;
+ }
+}