]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/blame - settings/install.php
Setup major reshuffle: split up in pre-auth: backend & user creation, and
[irc/unrealircd/unrealircd-webpanel.git] / settings / install.php
CommitLineData
78069032
VP
1<?php
2
3require_once "../common.php";
4
9680dd58 5/* Get the base url */
973acaa9 6$uri = $_SERVER['REQUEST_URI'];
9680dd58 7$tok = split($uri, "/");
2dbe2544 8$base_url = "";
9680dd58
VP
9for ($i=0; isset($tok[$i]); $i++)
10{
2dbe2544 11 if ($tok[$i] == "settings" && strstr($tok[$i + 1], "install.php"))
9680dd58 12 {
9680dd58
VP
13 if ($i)
14 {
15 for($j=0; $j < $i; $j++)
16 {
17 strcat($base_url,$tok[$j]);
18 strcat($base_url,"/");
19 }
20 }
9680dd58
VP
21 }
22}
2dbe2544
VP
23if (!strlen($base_url))
24 $base_url = "/";
25define('BASE_URL', $base_url);
26
78069032
VP
27$writable = (is_writable("../config/")) ? true: false;
28?>
29<!DOCTYPE html>
30<head>
31<div class="media">
32<div class="media-body">
33
34 <meta name="viewport" content="width=device-width, initial-scale=1">
35 <meta name="HandheldFriendly" content="true">
36
78069032
VP
37
38
39 <!-- Latest compiled and minified CSS -->
40 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
41
42<!-- Font Awesome JS -->
43<script defer src="https://use.fontawesome.com/releases/v6.2.1/js/solid.js" integrity="sha384-tzzSw1/Vo+0N5UhStP3bvwWPq+uvzCMfrN1fEFe+xBmv1C/AtVX5K0uZtmcHitFZ" crossorigin="anonymous"></script>
44<script defer src="https://use.fontawesome.com/releases/v6.2.1/js/fontawesome.js" integrity="sha384-6OIrr52G08NpOFSZdxxz1xdNSndlD4vdcf/q2myIUVO0VsqaGHJsB0RaBE01VTOY" crossorigin="anonymous"></script>
45
46<!-- Font Awesome icons -->
47<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
2dbe2544 48<script src="../js/unrealircd-admin.js"></script>
78069032
VP
49<title>UnrealIRCd Panel</title>
50<link rel="icon" type="image/x-icon" href="<?php echo get_config("base_url"); ?>img/favicon.ico">
51
52<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
53<!-- Popper.JS -->
54<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
55<!-- Bootstrap JS -->
56<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
57</div></div>
58</head>
59
60<body role="document">
61
2dbe2544 62 <div class="container mt-4"><div class="row justify-content-center"><img src="../img/unreal.jpg" width="35px" height="35px" style="margin-right: 15px"><h3>UnrealIRCd Admin Panel Configuration and Setup</h3></div></div>
9680dd58 63<?php
78069032
VP
64
65 if (file_exists("../config/config.php"))
66 {
2dbe2544 67 ?><br><div class="container"><?php Message::Fail("You're already configured!"); ?>
78069032
VP
68 <br>
69 <a class="text-center btn btn-primary" href="<?php echo BASE_URL; ?>">Take me home!</a>
70 </div>
71 <?php
72 return;
73 }
2dbe2544 74 elseif (isset($_POST) && !empty($_POST))
9680dd58 75 {
2dbe2544
VP
76 ?><br><div class="container"><?php
77 $opts = (object)$_POST;
9680dd58 78 /* pre-load the appropriate auth plugin */
9680dd58 79 $auth_method = (isset($opts->auth_method)) ? $opts->auth_method : NULL;
2dbe2544
VP
80 $auth_method_name = NULL;
81 switch($auth_method)
82 {
83 case "sql_auth":
84 $auth_method_name = "SQLAuth";
85 break;
86 case "file_auth":
87 $auth_method_name = "FileAuth";
88 break;
89 }
9680dd58 90 if ($auth_method)
2dbe2544 91 $am = new Plugin($auth_method);
9680dd58 92 else
2dbe2544
VP
93 {
94 Message::Fail("Invalid parameters");
95 return;
96 }
97 if ($am->error)
98 {
99 Message::Fail("Couldn't load plugin \"$auth_method\": $am->error");
100 return;
101 }
102
54b9603c
BM
103 $config["base_url"] = BASE_URL;
104 $config["plugins"] = Array("$auth_method");
105 if ($auth_method == "sql_auth")
2dbe2544 106 {
54b9603c
BM
107 $config["mysql"] = [
108 "host" => $opts->sql_host,
109 "database" => $opts->sql_db,
110 "username" => $opts->sql_user,
111 "password" => $opts->sql_password,
b41fa16f 112 ];
54b9603c 113 }
b41fa16f 114
54b9603c
BM
115 /* First, write only the config file */
116 write_config_file();
117
118 if ($auth_method == "sql_auth")
119 if (!sql_auth::create_tables())
120 Message::Fail("Could not create SQL tables");
121
122 $user = [
123 "user_name" => $opts->account_user,
124 "user_pass" => $opts->account_password,
125 "fname" => $opts->account_fname,
126 "lname" => $opts->account_lname,
127 "user_bio" => $opts->account_bio,
128 "email" => $opts->account_email
129 ];
130
131 create_new_user($user);
132 $lkup = new PanelUser($opts->account_user);
133 if (!$lkup->id)
134 {
135 Message::Fail("Could not create user");
2dbe2544
VP
136 return;
137 }
54b9603c
BM
138 $lkup->add_permission(PERMISSION_MANAGE_USERS);
139
140 /* Now, write all the config (config.php + settings in DB) */
141 write_config();
142 ?>
143 <br>
144 The configuration file has been written. Now, log in to the panel to proceed with the rest of the installation.<br><br>
145 <a class="text-center btn btn-primary" href="<?php echo BASE_URL; ?>">Let's go!</a></div>
146 <?php
147 return;
9680dd58 148 }
78069032
VP
149
150?>
9680dd58
VP
151<style>
152 table tr td {
153 font-style: italic;
154 }
155</style>
54b9603c 156<?php if (!$writable) { ?>
78069032
VP
157<div id="page1" class="container">
158 <br>
54b9603c
BM
159 The admin panel needs to be able to write the config file.<br>
160 Please run: <code>sudo chown <?php echo get_current_user(); ?> <?php echo UPATH; ?> -R</code><br>
161 And after that, refresh this webpage.<br><br>
162 If you have any questions about this, read <a href="https://www.unrealircd.org/docs/UnrealIRCd_webpanel#Permissions" target="_blank">the installation manual on permissions</a>.
78069032 163</div>
54b9603c
BM
164<?php
165 die;
166} ?>
78069032
VP
167
168<!-- Form start -->
2dbe2544 169<form method="post">
78069032 170<div id="page3" class="container">
54b9603c 171 <h5>Authentication Backend</h5>
78069032 172 <br>
54b9603c 173 Which authentication backend would you like to use?
78069032
VP
174 <br><br>
175 Please choose from the available options:
176 <div class="form-group">
177 <div class="form-check">
178 <input class="form-check-input" type="radio" name="auth_method" id="file_auth_radio" value="file_auth">
179 <label class="form-check-label" for="file_auth_radio">
180 File-based Authentication (Uses local files as a database, no setup needed)
181 </label>
182 </div>
183 <div class="form-check">
184 <input class="form-check-input" type="radio" name="auth_method" id="sql_auth_radio" value="sql_auth">
185 <label class="form-check-label" for="sql_auth_radio">
186 SQL Authentication (Requires an SQL database)
187 </label>
188 </div>
189 </div>
190 <br>
191 <div id="sql_form" style="display:none">
192 Please enter your SQL information. <div id="sql_instructions" class="ml-4 btn btn-sm btn-info">View instructions</div>
193 <div class="form-group">
036c24c5
BM
194 <label for="sql_host">Hostname or IP</label>
195 <input name="sql_host" type="text" class="revalidation-needed-sql form-control" id="sql_host" aria-describedby="hostname_help" value="127.0.0.1">
78069032
VP
196 <small id="hostname_help" class="form-text text-muted">The hostname or IP address of your SQL server. You should use <code>127.0.0.1</code> for the same machine.</small>
197 </div>
198 <div class="form-group">
199 <label for="sql_db">Database name</label>
f0106ef0 200 <input name="sql_db" type="text" class="revalidation-needed-sql form-control" id="sql_db" aria-describedby="port_help">
78069032
VP
201 <small id="port_help" class="form-text text-muted">The name of the SQL database to write to and read from.</small>
202 </div>
203 <div class="form-group">
204 <label for="sql_username">Username</label>
f0106ef0 205 <input name="sql_user" type="text" class="revalidation-needed-sql form-control" id="sql_user" aria-describedby="username_help">
78069032
VP
206 <small id="username_help" class="form-text text-muted">The name of SQL user</small>
207 </div>
208 <div class="form-group">
209 <label for="sql_password">Password</label>
f0106ef0 210 <input name="sql_password" type="password" class="revalidation-needed-sql form-control" id="sql_password">
78069032
VP
211 </div>
212 </div>
213 <div class="text-center">
78069032
VP
214 <div id="page3_next" class="btn btn-primary ml-3">Next</div>
215 <div id="page3_test_connection" class="btn btn-primary ml-3" style="display: none">Test connection</div>
216 </div>
217</div>
f0106ef0 218<div id="page4" class="container" >
78069032
VP
219 <h5>Create your account</h5>
220 <br>
54b9603c 221 You need an account, let's make one.<br><br>
78069032 222 <div class="form-group">
f0106ef0 223 <label for="account_user" id="userlabel">Pick a username</label>
78069032 224 <input name="account_user" type="text" class="form-control" id="account_user" aria-describedby="username_help">
f0106ef0 225 <small id="username_help" class="form-text text-muted">Pick a username! Please make sure it's at least 3 characters long, contains no spaces, and is made of only letters and numbers.</small>
78069032
VP
226 </div>
227 <div class="form-group">
f0106ef0 228 <label for="account_password" id="passlabel">Password</label>
78069032
VP
229 <input name="account_password" type="password" class="form-control" id="account_password" aria-describedby="password_help">
230 <small id="password_help" class="form-text text-muted">Please choose a password that at least 8 characters long, contains at least one uppercase letter, one lowercase letter, one number and one symbol.</small>
231 </div>
232 <div class="form-group">
f0106ef0 233 <label for="account_password_conf" id="passconflabel">Confirm password</label>
78069032 234 <input name="account_password_conf" type="password" class="form-control" id="account_password_conf">
78069032
VP
235 </div>
236 <div class="form-group">
f0106ef0 237 <label for="account_email" id="emaillabel">Email address</label>
78069032 238 <input name="account_email" type="text" class="form-control" id="account_email" aria-describedby="email_help">
78069032
VP
239 </div>
240 <div class="form-group">
f0106ef0 241 <label for="account_fname" id="fnamelabel">First name</label>
9680dd58 242 <input name="account_fname" type="text" class="form-control" id="account_fname">
78069032
VP
243 </div>
244 <div class="form-group">
f0106ef0 245 <label for="account_lname" id="lnamelabel">Last name</label>
78069032
VP
246 <input name="account_lname" type="text" class="form-control" id="account_lname">
247 </div>
248 <div class="form-group">
f0106ef0 249 <label for="account_bio" id="biolabel">Bio</label>
78069032
VP
250 <textarea name="account_bio" type="text" class="form-control" id="account_bio"></textarea>
251 </div>
252 <div class="text-center">
253 <div id="page4_back" class="btn btn-secondary mr-3">Back</div>
9680dd58
VP
254 <button id="page4_next" type="submit" class="btn btn-primary ml-3">Submit</div>
255 </div>
256</div>
78069032
VP
257</form>
258<script>
259 let BASE_URL = '<?php echo BASE_URL; ?>';
260 let chmod_help = document.getElementById('chmod_help');
261
262 if (chmod_help)
263 chmod_help.addEventListener('click', e => {
264 window.open("https://www.unrealircd.org/docs/UnrealIRCd_webpanel#Permissions");
265 });
266
78069032 267 let page3 = document.getElementById('page3');
9680dd58 268 let page4 = document.getElementById('page4');
78069032
VP
269
270 let file_auth_radio = document.getElementById('file_auth_radio');
271 let sql_auth_radio = document.getElementById('sql_auth_radio');
272 let sql_form = document.getElementById('sql_form');
036c24c5 273 let sql_host = document.getElementById('sql_host');
78069032
VP
274 let sql_db = document.getElementById('sql_db');
275 let sql_user = document.getElementById('sql_user');
276 let sql_pass = document.getElementById('sql_password');
277 let sql_test_conn = document.getElementById('page3_test_connection');
78069032
VP
278 let page3_next = document.getElementById('page3_next');
279
78069032
VP
280 let page4_back = document.getElementById('page4_back');
281 let page4_next = document.getElementById('page4_next');
78069032 282
54b9603c 283 page4.style.display = 'none';
9680dd58 284
f0106ef0
VP
285 revalidate_sql = document.querySelectorAll('.revalidation-needed-sql');
286 for (let i = 0; i < revalidate_sql.length; i++)
287 {
288 revalidate_sql[i].addEventListener('input', e => {
289 page3_next.style.display = 'none';
290 sql_test_conn.innerHTML = 'Test connection';
291 sql_test_conn.style.display = '';
292 sql_test_conn.classList.remove('disabled');
293 });
294 }
9680dd58 295
78069032
VP
296 page3_next.addEventListener('click', e => {
297 page3.style.display = 'none';
298 page4.style.display = '';
299 });
300
301 file_auth_radio.addEventListener('click', e => {
302 if (file_auth_radio.checked){
303 sql_form.style.display = 'none';
304 sql_test_conn.style.display = 'none';
305 page3_next.style.display = '';
306 }
307 });
9680dd58 308
78069032
VP
309 sql_auth_radio.addEventListener('click', e => {
310 if (!file_auth_radio.checked){
311 sql_form.style.display = '';
312 sql_test_conn.style.display = '';
313 page3_next.style.display = 'none';
314 }
315 });
316
317 sql_instructions.addEventListener('click', e => {
318 window.open("https://www.unrealircd.org/docs/UnrealIRCd_webpanel#SQL_Authentication");
319 });
320
321 sql_test_conn.addEventListener('click', e => {
322 sql_test_conn.classList.add('disabled');
323 sql_test_conn.innerHTML = "Checking...";
f0106ef0 324 fetch(BASE_URL + 'api/installation.php?method=sql&host='+sql_host.value+'&database='+sql_db.value+'&user='+sql_user.value+'&password='+sql_pass.value)
78069032
VP
325 .then(response => response.json())
326 .then(data => {
327 if (data.success)
328 {
329 // do something with the JSON data
330 sql_test_conn.innerHTML = "Success!";
331 setTimeout(function() {
332 sql_test_conn.style.display = 'none';
333 page3_next.style.display = '';
334 }, 2000);
335 }
336 else
337 {
338 sql_test_conn.innerHTML = "Failed!";
339 setTimeout(function() {
340 sql_test_conn.innerHTML = "Test connection";
341 sql_test_conn.classList.remove('disabled');
342 }, 2000);
343 }
344 })
345 .catch(error => {
346 sql_test_conn.innerHTML = "Failed!";
347 setTimeout(function() {
348 sql_test_conn.innerHTML = "Test connection";
349 sql_test_conn.classList.remove('disabled');
350 }, 2000);
351 });
f0106ef0 352 });
78069032 353
f0106ef0
VP
354 user_name_label = document.getElementById('userlabel');
355 user_name = document.getElementById('account_user');
356 user_pass_label = document.getElementById('passlabel');
357 user_pass = document.getElementById('account_password');
358 user_pass2_label = document.getElementById('passconflabel');
359 user_pass2 = document.getElementById('account_password_conf');
360 user_email_label = document.getElementById('emaillabel');
361 user_email = document.getElementById('account_email');
9680dd58
VP
362 user_fname = document.getElementById('account_fname');
363 user_lname = document.getElementById('account_lname');
364 user_bio = document.getElementById('account_bio');
f0106ef0 365
78069032
VP
366 page4_back.addEventListener('click', e => {
367 page4.style.display = 'none';
368 page3.style.display = '';
369 });
f0106ef0 370
78069032 371 page4_next.addEventListener('click', e => {
f0106ef0
VP
372
373 /* Form validation */
374 let req_not_met = ' <small style="color:red">Does not meet requirements</small>';
375 let errs = 0;
376 const regex_username = /^[a-zA-Z\d]{3,}$/;
377 if (!regex_username.test(user_name.value))
378 {
379 user_name_label.innerHTML = 'Pick a username!' + req_not_met;
380 errs++;
381 } else
382 user_name_label.innerHTML = 'Pick a username!';
383
384 let regex_pass = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$/;
385 if (!regex_pass.test(user_pass.value))
386 {
387 user_pass_label.innerHTML = 'Password' + req_not_met;
388 errs++;
389 } else
390 user_pass_label.innerHTML = 'Password';
391
392 if (user_pass2.value !== user_pass.value)
393 {
394 user_pass2_label.innerHTML = 'Confirm password <small style="color:red">Passwords do not match</small>';
395 errs++;
396 } else
397 user_pass2_label.innerHTML = 'Confirm password';
398
399 const regex_email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
f0106ef0
VP
400 if (!regex_email.test(user_email.value))
401 {
402 user_email_label.innerHTML = 'Email address' + req_not_met;
403 errs++;
404 }
405 else
406 user_email_label.innerHTML = 'Email address';
407
408 if (errs)
9680dd58 409 {
54b9603c
BM
410 e.preventDefault();
411 return false;
9680dd58
VP
412 }
413
78069032 414 page4.style.display = 'none';
78069032 415 });
78069032 416</script>