Browse Source

Add Portal API integration, add icon/style settings, add navbar and icon

 options to PAGES
Skylar Ittner 2 years ago
parent
commit
3110011596
11 changed files with 545 additions and 262 deletions
  1. 57
    13
      app.php
  2. 2
    1
      composer.json
  3. 229
    1
      composer.lock
  4. 11
    4
      index.php
  5. 2
    18
      lang/en_us.php
  6. 148
    223
      lib/login.php
  7. 1
    1
      nbproject/project.xml
  8. 3
    1
      pages.php
  9. 14
    0
      settings.template.php
  10. BIN
      static/img/logo.png
  11. 78
    0
      static/img/logo.svg

+ 57
- 13
app.php View File

@@ -36,10 +36,18 @@ if (!is_empty($_GET['page'])) {
36 36
         <div class="container">
37 37
             <div class="row">
38 38
                 <div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4">
39
-                    <img class="img-responsive banner-image" src="static/img/banner.png" />
39
+                    <?php
40
+                    if ((SHOW_ICON == "both" || SHOW_ICON == "app") && ICON_POSITION != "menu") {
41
+                        if (MENU_BAR_STYLE != "fixed") {
42
+                            ?>
43
+                            <img class="img-responsive banner-image" src="static/img/logo.png" />
44
+                            <?php
45
+                        }
46
+                    }
47
+                    ?>
40 48
                 </div>
41 49
             </div>
42
-            <nav class="navbar navbar-inverse">
50
+            <nav class="navbar navbar-inverse navbar-<?php echo MENU_BAR_STYLE; ?>-top">
43 51
                 <div class="container-fluid">
44 52
                     <div class="navbar-header">
45 53
                         <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
@@ -48,34 +56,70 @@ if (!is_empty($_GET['page'])) {
48 56
                             <span class="icon-bar"></span>
49 57
                             <span class="icon-bar"></span>
50 58
                         </button>
51
-                        <a class="navbar-brand" href="app.php?page=home">
59
+                        <?php
60
+                        if (SHOW_ICON == "both" || SHOW_ICON == "app") {
61
+                            if (MENU_BAR_STYLE == "fixed" || ICON_POSITION == "menu") {
62
+                                ?>
63
+                                <a class="navbar-brand" href="app.php">
64
+                                    <img style="height: 35px; padding-bottom: 12px; padding-left: 5px;" src="static/img/logo.png" />
65
+                                </a>
66
+                                <?php
67
+                            }
68
+                        }
69
+                        ?>
70
+                        <a class="navbar-brand" href="app.php">
52 71
                             <?php
72
+                            echo SITE_TITLE;
53 73
                             // add breadcrumb-y thing
54 74
                             //lang("home");
55 75
                             //echo " <i class=\"fa fa-caret-right\"></i> ";
56
-                            lang(PAGES[$pageid]['title']);
76
+                            //lang(PAGES[$pageid]['title']);
57 77
                             ?>
58 78
                         </a>
59 79
                     </div>
60 80
 
61 81
                     <div class="collapse navbar-collapse" id="navbar-collapse">
62 82
                         <ul class="nav navbar-nav">
83
+                            <?php
84
+                            foreach (PAGES as $id => $pg) {
85
+                                if ($pg['navbar'] === TRUE) {
86
+                                    if ($pageid == $id) {
87
+                                        ?>
88
+                                        <li class="active">
89
+                                            <?php
90
+                                        } else {
91
+                                            ?>
92
+                                        <li>
93
+                                        <?php } ?>
94
+                                        <a href="app.php?page=<?php echo $id; ?>">
95
+                                            <?php
96
+                                            if (isset($pg['icon'])) {
97
+                                                ?>
98
+                                                <i class="fa fa-<?php echo $pg['icon']; ?> fa-fw"></i> 
99
+                                            <?php } ?>
100
+                                            <?php lang($pg['title']) ?>
101
+                                        </a>
102
+                                    </li>
103
+                                    <?php
104
+                                }
105
+                            }
106
+                            ?>
63 107
                         </ul>
64 108
                         <ul class="nav navbar-nav navbar-right">
65
-                            <li class="dropdown">
66
-                                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-gears fa-fw"></i> <?php lang("options") ?> <span class="caret"></span></a>
67
-                                <ul class="dropdown-menu" role="menu">
68
-                                    <li><a href="app.php?page=security"><i class="fa fa-lock fa-fw"></i> <?php lang("account security") ?></a></li>
69
-                                    <li class="divider"></li>
70
-                                    <li><a href="action.php?action=signout"><i class="fa fa-sign-out fa-fw"></i> <?php lang("sign out") ?></a></li>
71
-                                </ul>
72
-                            </li>
109
+                            <li><a href="action.php?action=signout"><i class="fa fa-sign-out fa-fw"></i> <?php lang("sign out") ?></a></li>
73 110
                         </ul>
74 111
                     </div>
75 112
                 </div>
76 113
             </nav>
77 114
             <?php
78
-            // Alert messages
115
+            if (MENU_BAR_STYLE == "fixed") {
116
+                ?>
117
+                <div style="height: 75px;"></div>
118
+                <?php
119
+            }
120
+            ?>
121
+            <?php
122
+// Alert messages
79 123
             if (!is_empty($_GET['msg']) && array_key_exists($_GET['msg'], MESSAGES)) {
80 124
                 // optional string generation argument
81 125
                 if (is_empty($_GET['arg'])) {

+ 2
- 1
composer.json View File

@@ -4,7 +4,8 @@
4 4
     "type": "project",
5 5
     "require": {
6 6
         "catfan/medoo": "^1.2",
7
-        "spomky-labs/otphp": "^8.3"
7
+        "spomky-labs/otphp": "^8.3",
8
+        "guzzlehttp/guzzle": "^6.2"
8 9
     },
9 10
     "license": "MIT",
10 11
     "authors": [

+ 229
- 1
composer.lock View File

@@ -4,7 +4,7 @@
4 4
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 5
         "This file is @generated automatically"
6 6
     ],
7
-    "content-hash": "51c1672b4dea32e60865b4c0cd9ff8e1",
7
+    "content-hash": "e0730a4c33d1a1cbf8738481ba9a1f1e",
8 8
     "packages": [
9 9
         {
10 10
             "name": "beberlei/assert",
@@ -170,6 +170,184 @@
170 170
             ],
171 171
             "time": "2016-05-05T11:49:03+00:00"
172 172
         },
173
+        {
174
+            "name": "guzzlehttp/guzzle",
175
+            "version": "6.2.3",
176
+            "source": {
177
+                "type": "git",
178
+                "url": "https://github.com/guzzle/guzzle.git",
179
+                "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006"
180
+            },
181
+            "dist": {
182
+                "type": "zip",
183
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006",
184
+                "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006",
185
+                "shasum": ""
186
+            },
187
+            "require": {
188
+                "guzzlehttp/promises": "^1.0",
189
+                "guzzlehttp/psr7": "^1.4",
190
+                "php": ">=5.5"
191
+            },
192
+            "require-dev": {
193
+                "ext-curl": "*",
194
+                "phpunit/phpunit": "^4.0",
195
+                "psr/log": "^1.0"
196
+            },
197
+            "type": "library",
198
+            "extra": {
199
+                "branch-alias": {
200
+                    "dev-master": "6.2-dev"
201
+                }
202
+            },
203
+            "autoload": {
204
+                "files": [
205
+                    "src/functions_include.php"
206
+                ],
207
+                "psr-4": {
208
+                    "GuzzleHttp\\": "src/"
209
+                }
210
+            },
211
+            "notification-url": "https://packagist.org/downloads/",
212
+            "license": [
213
+                "MIT"
214
+            ],
215
+            "authors": [
216
+                {
217
+                    "name": "Michael Dowling",
218
+                    "email": "mtdowling@gmail.com",
219
+                    "homepage": "https://github.com/mtdowling"
220
+                }
221
+            ],
222
+            "description": "Guzzle is a PHP HTTP client library",
223
+            "homepage": "http://guzzlephp.org/",
224
+            "keywords": [
225
+                "client",
226
+                "curl",
227
+                "framework",
228
+                "http",
229
+                "http client",
230
+                "rest",
231
+                "web service"
232
+            ],
233
+            "time": "2017-02-28T22:50:30+00:00"
234
+        },
235
+        {
236
+            "name": "guzzlehttp/promises",
237
+            "version": "v1.3.1",
238
+            "source": {
239
+                "type": "git",
240
+                "url": "https://github.com/guzzle/promises.git",
241
+                "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
242
+            },
243
+            "dist": {
244
+                "type": "zip",
245
+                "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
246
+                "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
247
+                "shasum": ""
248
+            },
249
+            "require": {
250
+                "php": ">=5.5.0"
251
+            },
252
+            "require-dev": {
253
+                "phpunit/phpunit": "^4.0"
254
+            },
255
+            "type": "library",
256
+            "extra": {
257
+                "branch-alias": {
258
+                    "dev-master": "1.4-dev"
259
+                }
260
+            },
261
+            "autoload": {
262
+                "psr-4": {
263
+                    "GuzzleHttp\\Promise\\": "src/"
264
+                },
265
+                "files": [
266
+                    "src/functions_include.php"
267
+                ]
268
+            },
269
+            "notification-url": "https://packagist.org/downloads/",
270
+            "license": [
271
+                "MIT"
272
+            ],
273
+            "authors": [
274
+                {
275
+                    "name": "Michael Dowling",
276
+                    "email": "mtdowling@gmail.com",
277
+                    "homepage": "https://github.com/mtdowling"
278
+                }
279
+            ],
280
+            "description": "Guzzle promises library",
281
+            "keywords": [
282
+                "promise"
283
+            ],
284
+            "time": "2016-12-20T10:07:11+00:00"
285
+        },
286
+        {
287
+            "name": "guzzlehttp/psr7",
288
+            "version": "1.4.2",
289
+            "source": {
290
+                "type": "git",
291
+                "url": "https://github.com/guzzle/psr7.git",
292
+                "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
293
+            },
294
+            "dist": {
295
+                "type": "zip",
296
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
297
+                "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
298
+                "shasum": ""
299
+            },
300
+            "require": {
301
+                "php": ">=5.4.0",
302
+                "psr/http-message": "~1.0"
303
+            },
304
+            "provide": {
305
+                "psr/http-message-implementation": "1.0"
306
+            },
307
+            "require-dev": {
308
+                "phpunit/phpunit": "~4.0"
309
+            },
310
+            "type": "library",
311
+            "extra": {
312
+                "branch-alias": {
313
+                    "dev-master": "1.4-dev"
314
+                }
315
+            },
316
+            "autoload": {
317
+                "psr-4": {
318
+                    "GuzzleHttp\\Psr7\\": "src/"
319
+                },
320
+                "files": [
321
+                    "src/functions_include.php"
322
+                ]
323
+            },
324
+            "notification-url": "https://packagist.org/downloads/",
325
+            "license": [
326
+                "MIT"
327
+            ],
328
+            "authors": [
329
+                {
330
+                    "name": "Michael Dowling",
331
+                    "email": "mtdowling@gmail.com",
332
+                    "homepage": "https://github.com/mtdowling"
333
+                },
334
+                {
335
+                    "name": "Tobias Schultze",
336
+                    "homepage": "https://github.com/Tobion"
337
+                }
338
+            ],
339
+            "description": "PSR-7 message implementation that also provides common utility methods",
340
+            "keywords": [
341
+                "http",
342
+                "message",
343
+                "request",
344
+                "response",
345
+                "stream",
346
+                "uri",
347
+                "url"
348
+            ],
349
+            "time": "2017-03-20T17:10:46+00:00"
350
+        },
173 351
         {
174 352
             "name": "paragonie/random_compat",
175 353
             "version": "v2.0.10",
@@ -218,6 +396,56 @@
218 396
             ],
219 397
             "time": "2017-03-13T16:27:32+00:00"
220 398
         },
399
+        {
400
+            "name": "psr/http-message",
401
+            "version": "1.0.1",
402
+            "source": {
403
+                "type": "git",
404
+                "url": "https://github.com/php-fig/http-message.git",
405
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
406
+            },
407
+            "dist": {
408
+                "type": "zip",
409
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
410
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
411
+                "shasum": ""
412
+            },
413
+            "require": {
414
+                "php": ">=5.3.0"
415
+            },
416
+            "type": "library",
417
+            "extra": {
418
+                "branch-alias": {
419
+                    "dev-master": "1.0.x-dev"
420
+                }
421
+            },
422
+            "autoload": {
423
+                "psr-4": {
424
+                    "Psr\\Http\\Message\\": "src/"
425
+                }
426
+            },
427
+            "notification-url": "https://packagist.org/downloads/",
428
+            "license": [
429
+                "MIT"
430
+            ],
431
+            "authors": [
432
+                {
433
+                    "name": "PHP-FIG",
434
+                    "homepage": "http://www.php-fig.org/"
435
+                }
436
+            ],
437
+            "description": "Common interface for HTTP messages",
438
+            "homepage": "https://github.com/php-fig/http-message",
439
+            "keywords": [
440
+                "http",
441
+                "http-message",
442
+                "psr",
443
+                "psr-7",
444
+                "request",
445
+                "response"
446
+            ],
447
+            "time": "2016-08-06T14:39:51+00:00"
448
+        },
221 449
         {
222 450
             "name": "spomky-labs/otphp",
223 451
             "version": "v8.3.0",

+ 11
- 4
index.php View File

@@ -39,9 +39,12 @@ if ($VARS['progress'] == "1") {
39 39
     }
40 40
 } else if ($VARS['progress'] == "2") {
41 41
     if (verifyTOTP($VARS['username'], $VARS['authcode'])) {
42
-        doLoginUser($VARS['username'], $VARS['password']);
43
-        header('Location: app.php');
44
-        die("Logged in, go to app.php");
42
+        if (doLoginUser($VARS['username'])) {
43
+            header('Location: app.php');
44
+            die("Logged in, go to app.php");
45
+        } else {
46
+            $alert = lang("login server user data error", false);
47
+        }
45 48
     } else {
46 49
         $alert = lang("2fa incorrect", false);
47 50
     }
@@ -64,7 +67,11 @@ if ($VARS['progress'] == "1") {
64 67
             <div class="row">
65 68
                 <div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4">
66 69
                     <div>
67
-                        <img class="img-responsive banner-image" src="static/img/banner.png" />
70
+                        <?php
71
+                        if (SHOW_ICON == "both" || SHOW_ICON == "index") {
72
+                            ?>
73
+                            <img class="img-responsive banner-image" src="static/img/logo.png" />
74
+                        <?php } ?>
68 75
                     </div>
69 76
                     <div class="panel panel-primary">
70 77
                         <div class="panel-heading">

+ 2
- 18
lang/en_us.php View File

@@ -13,30 +13,14 @@ define("STRINGS", [
13 13
     "password expired" => "You must change your password before continuing.",
14 14
     "account terminated" => "Account terminated.  Access denied.",
15 15
     "account state error" => "Your account state is not stable.  Log out, restart your browser, and try again.",
16
-    "password on 500 list" => "The given password is ranked number {arg} out of the 500 most common passwords.  Try a different one.",
17 16
     "welcome user" => "Welcome, {user}!",
18
-    "change password" => "Change password",
19
-    "security options" => "Security options",
20
-    "account security" => "Account security",
21 17
     "sign out" => "Sign out",
22 18
     "settings" => "Settings",
23 19
     "options" => "Options",
24 20
     "404 error" => "404 Error",
25 21
     "page not found" => "Page not found.",
26
-    "current password incorrect" => "The current password is incorrect.  Try again.",
27
-    "new password mismatch" => "The new passwords did not match.  Try again.",
28
-    "weak password" => "Password does not meet requirements.",
29
-    "password updated" => "Password updated successfully.",
30
-    "setup 2fa" => "Setup 2-factor authentication",
31
-    "2fa removed" => "2-factor authentication disabled.",
32
-    "2fa enabled" => "2-factor authentication activated.",
33
-    "remove 2fa" => "Disable 2-factor authentication",
34
-    "2fa explained" => "2-factor authentication adds more security to your account. You'll need an app such as Google Authenticator on your smartphone. When you have the app installed, you can enable 2-factor authentication by clicking the button below and scanning a QR code with the app. Whenever you sign in in the future, you'll need to input a six-digit code from your phone into the login page when prompted. You can disable 2-factor authentication from this page if you change your mind.",
35
-    "2fa active" => "2-factor authentication is active on your account.  To remove 2fa, reset your authentication secret, or change to a new security device, click the button below.",
36
-    "enable 2fa" => "Enable 2-factor authentication",
37
-    "scan 2fa qrcode" => "Scan the QR Code with the authenticator app, or enter the secret key manually.",
38
-    "confirm 2fa" => "Finish setup",
39 22
     "invalid parameters" => "Invalid request parameters.",
40
-    "ldap server error" => "The LDAP server returned an error: {arg}",
23
+    "login server error" => "The login server returned an error: {arg}",
24
+    "login server user data error" => "The login server refused to provide account information.  Try again or contact technical support.",
41 25
     "home" => "Home",
42 26
 ]);

+ 148
- 223
lib/login.php View File

@@ -1,147 +1,98 @@
1 1
 <?php
2 2
 
3 3
 /**
4
- * Authentication and account functions
4
+ * Authentication and account functions.  Connects to a Portal instance.
5 5
  */
6
-use Base32\Base32;
7
-use OTPHP\TOTP;
8
-use LdapTools\LdapManager;
9
-use LdapTools\Connection\ADResponseCodes;
10
-
11 6
 ////////////////////////////////////////////////////////////////////////////////
12 7
 //                           Account handling                                 //
13 8
 ////////////////////////////////////////////////////////////////////////////////
14 9
 
15 10
 /**
16
- * Add a user to the system.  /!\ Assumes input is OK /!\
17
- * @param string $username Username, saved in lowercase.
18
- * @param string $password Password, will be hashed before saving.
19
- * @param string $realname User's real legal name
20
- * @param string $email User's email address.
21
- * @return int The new user's ID number in the database.
22
- */
23
-function adduser($username, $password, $realname, $email = null, $phone1 = "", $phone2 = "") {
24
-    global $database;
25
-    $database->debug()->insert('accounts', [
26
-        'username' => strtolower($username),
27
-        'password' => (is_null($password) ? null : encryptPassword($password)),
28
-        'realname' => $realname,
29
-        'email' => $email,
30
-        'phone1' => $phone1,
31
-        'phone2' => $phone2,
32
-        'acctstatus' => 1
33
-    ]);
34
-
35
-    return $database->id();
36
-}
37
-
38
-/**
39
- * Get where a user's account actually is.
40
- * @param string $username
41
- * @return string "LDAP", "LOCAL", "LDAP_ONLY", or "NONE".
42
- */
43
-function account_location($username, $password) {
44
-    global $database;
45
-    $user_exists = user_exists($username);
46
-    if (!$user_exists && !LDAP_ENABLED) {
47
-        return false;
48
-    }
49
-    if ($user_exists) {
50
-        $userinfo = $database->select('accounts', ['password'], ['username' => $username])[0];
51
-        // if password empty, it's an LDAP user
52
-        if (is_empty($userinfo['password']) && LDAP_ENABLED) {
53
-            return "LDAP";
54
-        } else if (is_empty($userinfo['password']) && !LDAP_ENABLED) {
55
-            return "NONE";
56
-        } else {
57
-            return "LOCAL";
58
-        }
59
-    } else {
60
-        if (user_exists_ldap($username, $password)) {
61
-            return "LDAP_ONLY";
62
-        } else {
63
-            return "NONE";
64
-        }
65
-    }
66
-}
67
-
68
-/**
69
- * Checks the given credentials against the database.
11
+ * Checks the given credentials against the API.
70 12
  * @param string $username
71 13
  * @param string $password
72 14
  * @return boolean True if OK, else false
73 15
  */
74 16
 function authenticate_user($username, $password) {
75
-    global $database;
76
-    global $ldap_config;
77
-    if (is_empty($username) || is_empty($password)) {
78
-        return false;
17
+    $client = new GuzzleHttp\Client();
18
+
19
+    $response = $client
20
+            ->request('POST', PORTAL_API, [
21
+        'form_params' => [
22
+            'key' => PORTAL_KEY,
23
+            'action' => "auth",
24
+            'username' => $username,
25
+            'password' => $password
26
+        ]
27
+    ]);
28
+
29
+    if ($response->getStatusCode() > 299) {
30
+        sendError("Login server error: " . $response->getBody());
79 31
     }
80
-    $loc = account_location($username, $password);
81
-    if ($loc == "NONE") {
82
-        return false;
83
-    } else if ($loc == "LOCAL") {
84
-        $hash = $database->select('accounts', ['password'], ['username' => $username, "LIMIT" => 1])[0]['password'];
85
-        return (comparePassword($password, $hash));
86
-    } else if ($loc == "LDAP") {
87
-        return authenticate_user_ldap($username, $password);
88
-    } else if ($loc == "LDAP_ONLY") {
89
-        if (authenticate_user_ldap($username, $password) === TRUE) {
90
-            try {
91
-                $user = (new LdapManager($ldap_config))->getRepository('user')->findOneByUsername($username);
92
-                var_dump($user);
93
-                adduser($user->getUsername(), null, $user->getName(), ($user->hasEmailAddress() ? $user->getEmailAddress() : null));
94
-                return true;
95
-            } catch (Exception $e) {
96
-                sendError("LDAP error: " . $e->getMessage());
97
-            }
98
-        } else {
99
-            return false;
100
-        }
32
+
33
+    $resp = json_decode($response->getBody(), TRUE);
34
+    if ($resp['status'] == "OK") {
35
+        return true;
101 36
     } else {
102 37
         return false;
103 38
     }
104 39
 }
105 40
 
106 41
 /**
107
- * Check if a username exists in the local database.
42
+ * Check if a username exists.
108 43
  * @param String $username
109 44
  */
110 45
 function user_exists($username) {
111
-    global $database;
112
-    return $database->has('accounts', ['username' => $username, "LIMIT" => QUERY_LIMIT]);
46
+    $client = new GuzzleHttp\Client();
47
+
48
+    $response = $client
49
+            ->request('POST', PORTAL_API, [
50
+        'form_params' => [
51
+            'key' => PORTAL_KEY,
52
+            'action' => "userexists",
53
+            'username' => $username
54
+        ]
55
+    ]);
56
+
57
+    if ($response->getStatusCode() > 299) {
58
+        sendError("Login server error: " . $response->getBody());
59
+    }
60
+
61
+    $resp = json_decode($response->getBody(), TRUE);
62
+    if ($resp['status'] == "OK" && $resp['exists'] === true) {
63
+        return true;
64
+    } else {
65
+        return false;
66
+    }
113 67
 }
114 68
 
115 69
 /**
116 70
  * Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED,
117 71
  * CHANGE_PASSWORD, or ALERT_ON_ACCESS
118
- * @global $database $database
119 72
  * @param string $username
120 73
  * @return string
121 74
  */
122 75
 function get_account_status($username) {
123
-    global $database;
124
-    $loc = account_location($username);
125
-    if ($loc == "LOCAL") {
126
-        $statuscode = $database->select('accounts', [
127
-                    '[>]acctstatus' => [
128
-                        'acctstatus' => 'statusid'
129
-                    ]
130
-                        ], [
131
-                    'accounts.acctstatus',
132
-                    'acctstatus.statuscode'
133
-                        ], [
134
-                    'username' => $username,
135
-                    "LIMIT" => 1
136
-                        ]
137
-                )[0]['statuscode'];
138
-        return $statuscode;
139
-    } else if ($loc == "LDAP") {
140
-        // TODO: Read actual account status from AD servers
141
-        return "NORMAL";
76
+    $client = new GuzzleHttp\Client();
77
+
78
+    $response = $client
79
+            ->request('POST', PORTAL_API, [
80
+        'form_params' => [
81
+            'key' => PORTAL_KEY,
82
+            'action' => "acctstatus",
83
+            'username' => $username
84
+        ]
85
+    ]);
86
+
87
+    if ($response->getStatusCode() > 299) {
88
+        sendError("Login server error: " . $response->getBody());
89
+    }
90
+
91
+    $resp = json_decode($response->getBody(), TRUE);
92
+    if ($resp['status'] == "OK") {
93
+        return $resp['account'];
142 94
     } else {
143
-        // account isn't setup properly
144
-        return "LOCKED_OR_DISABLED";
95
+        return false;
145 96
     }
146 97
 }
147 98
 
@@ -150,93 +101,64 @@ function get_account_status($username) {
150 101
 ////////////////////////////////////////////////////////////////////////////////
151 102
 
152 103
 /**
153
- * Setup $_SESSION values to log in a user
104
+ * Setup $_SESSION values with user data and set loggedin flag to true
154 105
  * @param string $username
155 106
  */
156
-function doLoginUser($username, $password) {
157
-    global $database;
158
-    $userinfo = $database->select('accounts', ['email', 'uid', 'realname'], ['username' => $username])[0];
159
-    $_SESSION['username'] = $username;
160
-    $_SESSION['uid'] = $userinfo['uid'];
161
-    $_SESSION['email'] = $userinfo['email'];
162
-    $_SESSION['realname'] = $userinfo['realname'];
163
-    $_SESSION['password'] = $password; // needed for things like EWS
164
-    $_SESSION['loggedin'] = true;
165
-}
166
-
167
-/**
168
- * Send an alert email to the system admin
169
- * 
170
- * Used when an account with the status ALERT_ON_ACCESS logs in
171
- * @param String $username the account username
172
- */
173
-function sendLoginAlertEmail($username) {
174
-    // TODO: add email code
175
-}
176
-
177
-////////////////////////////////////////////////////////////////////////////////
178
-//                              LDAP handling                                 //
179
-////////////////////////////////////////////////////////////////////////////////
107
+function doLoginUser($username) {
108
+    $client = new GuzzleHttp\Client();
109
+
110
+    $response = $client
111
+            ->request('POST', PORTAL_API, [
112
+        'form_params' => [
113
+            'key' => PORTAL_KEY,
114
+            'action' => "userinfo",
115
+            'username' => $username
116
+        ]
117
+    ]);
180 118
 
181
-/**
182
- * Checks the given credentials against the LDAP server.
183
- * @param string $username
184
- * @param string $password
185
- * @return mixed True if OK, else false or the error code from the server
186
- */
187
-function authenticate_user_ldap($username, $password) {
188
-    global $ldap_config;
189
-    if (is_empty($username) || is_empty($password)) {
190
-        return false;
119
+    if ($response->getStatusCode() > 299) {
120
+        sendError("Login server error: " . $response->getBody());
191 121
     }
192
-    $ldapManager = new LdapManager($ldap_config);
193
-    $msg = "";
194
-    $code = 0;
195
-    if ($ldapManager->authenticate($username, $password, $msg, $code)) {
122
+
123
+    $resp = json_decode($response->getBody(), TRUE);
124
+    var_dump($resp);
125
+    if ($resp['status'] == "OK") {
126
+        $userinfo = $resp['data'];
127
+        $_SESSION['username'] = $username;
128
+        $_SESSION['uid'] = $userinfo['uid'];
129
+        $_SESSION['email'] = $userinfo['email'];
130
+        $_SESSION['realname'] = $userinfo['name'];
131
+        $_SESSION['password'] = $password;
132
+        $_SESSION['loggedin'] = true;
196 133
         return true;
197 134
     } else {
198
-        return $code;
135
+        return false;
199 136
     }
200 137
 }
201 138
 
202
-/**
203
- * Check if a username exists on the LDAP server.
204
- * @global type $ldap_config
205
- * @param type $username
206
- * @return boolean true if yes, else false
207
- */
208
-function user_exists_ldap($username, $password) {
209
-    global $ldap_config;
210
-    $ldap = new LdapManager($ldap_config);
211
-    if (!$ldap->authenticate($username, $password, $message, $code)) {
212
-        switch ($code) {
213
-            case ADResponseCodes::ACCOUNT_INVALID:
214
-                return false;
215
-            case ADResponseCodes::ACCOUNT_CREDENTIALS_INVALID:
216
-                return true;
217
-            case ADResponseCodes::ACCOUNT_RESTRICTIONS:
218
-                return true;
219
-            case ADResponseCodes::ACCOUNT_RESTRICTIONS_TIME:
220
-                return true;
221
-            case ADResponseCodes::ACCOUNT_RESTRICTIONS_DEVICE:
222
-                return true;
223
-            case ADResponseCodes::ACCOUNT_PASSWORD_EXPIRED:
224
-                return true;
225
-            case ADResponseCodes::ACCOUNT_DISABLED:
226
-                return true;
227
-            case ADResponseCodes::ACCOUNT_CONTEXT_IDS:
228
-                return true;
229
-            case ADResponseCodes::ACCOUNT_EXPIRED:
230
-                return false;
231
-            case ADResponseCodes::ACCOUNT_PASSWORD_MUST_CHANGE:
232
-                return true;
233
-            case ADResponseCodes::ACCOUNT_LOCKED:
234
-                return true;
235
-            default:
236
-                return false;
237
-        }
139
+function simLogin($username, $password) {
140
+    $client = new GuzzleHttp\Client();
141
+
142
+    $response = $client
143
+            ->request('POST', PORTAL_API, [
144
+        'form_params' => [
145
+            'key' => PORTAL_KEY,
146
+            'action' => "login",
147
+            'username' => $username,
148
+            'password' => $password
149
+        ]
150
+    ]);
151
+
152
+    if ($response->getStatusCode() > 299) {
153
+        sendError("Login server error: " . $response->getBody());
154
+    }
155
+
156
+    $resp = json_decode($response->getBody(), TRUE);
157
+    if ($resp['status'] == "OK") {
158
+        return true;
159
+    } else {
160
+        return $resp['msg'];
238 161
     }
239
-    return true;
240 162
 }
241 163
 
242 164
 ////////////////////////////////////////////////////////////////////////////////
@@ -245,43 +167,31 @@ function user_exists_ldap($username, $password) {
245 167
 
246 168
 /**
247 169
  * Check if a user has TOTP setup
248
- * @global $database $database
249 170
  * @param string $username
250 171
  * @return boolean true if TOTP secret exists, else false
251 172
  */
252 173
 function userHasTOTP($username) {
253
-    global $database;
254
-    $secret = $database->select('accounts', 'authsecret', ['username' => $username])[0];
255
-    if (is_empty($secret)) {
256
-        return false;
257
-    }
258
-    return true;
259
-}
174
+    $client = new GuzzleHttp\Client();
175
+
176
+    $response = $client
177
+            ->request('POST', PORTAL_API, [
178
+        'form_params' => [
179
+            'key' => PORTAL_KEY,
180
+            'action' => "hastotp",
181
+            'username' => $username
182
+        ]
183
+    ]);
260 184
 
261
-/**
262
- * Generate a TOTP secret for the given user.
263
- * @param string $username
264
- * @return string OTP provisioning URI (for generating a QR code)
265
- */
266
-function newTOTP($username) {
267
-    global $database;
268
-    $secret = random_bytes(20);
269
-    $encoded_secret = Base32::encode($secret);
270
-    $userdata = $database->select('accounts', ['email', 'authsecret', 'realname'], ['username' => $username])[0];
271
-    $totp = new TOTP((is_null($userdata['email']) ? $userdata['realname'] : $userdata['email']), $encoded_secret);
272
-    $totp->setIssuer(SYSTEM_NAME);
273
-    return $totp->getProvisioningUri();
274
-}
185
+    if ($response->getStatusCode() > 299) {
186
+        sendError("Login server error: " . $response->getBody());
187
+    }
275 188
 
276
-/**
277
- * Save a TOTP secret for the user.
278
- * @global $database $database
279
- * @param string $username
280
- * @param string $secret
281
- */
282
-function saveTOTP($username, $secret) {
283
-    global $database;
284
-    $database->update('accounts', ['authsecret' => $secret], ['username' => $username]);
189
+    $resp = json_decode($response->getBody(), TRUE);
190
+    if ($resp['status'] == "OK") {
191
+        return $resp['otp'];
192
+    } else {
193
+        return false;
194
+    }
285 195
 }
286 196
 
287 197
 /**
@@ -292,11 +202,26 @@ function saveTOTP($username, $secret) {
292 202
  * @return boolean true if it's legit, else false
293 203
  */
294 204
 function verifyTOTP($username, $code) {
295
-    global $database;
296
-    $userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0];
297
-    if (is_empty($userdata['authsecret'])) {
205
+    $client = new GuzzleHttp\Client();
206
+
207
+    $response = $client
208
+            ->request('POST', PORTAL_API, [
209
+        'form_params' => [
210
+            'key' => PORTAL_KEY,
211
+            'action' => "verifytotp",
212
+            'username' => $username,
213
+            'code' => $code
214
+        ]
215
+    ]);
216
+
217
+    if ($response->getStatusCode() > 299) {
218
+        sendError("Login server error: " . $response->getBody());
219
+    }
220
+
221
+    $resp = json_decode($response->getBody(), TRUE);
222
+    if ($resp['status'] == "OK") {
223
+        return $resp['valid'];
224
+    } else {
298 225
         return false;
299 226
     }
300
-    $totp = new TOTP(null, $userdata['authsecret']);
301
-    return $totp->verify($code);
302 227
 }

+ 1
- 1
nbproject/project.xml View File

@@ -3,7 +3,7 @@
3 3
     <type>org.netbeans.modules.php.project</type>
4 4
     <configuration>
5 5
         <data xmlns="http://www.netbeans.org/ns/php-project/1">
6
-            <name>WebAppTemplate</name>
6
+            <name>BusinessAppTemplate</name>
7 7
         </data>
8 8
     </configuration>
9 9
 </project>

+ 3
- 1
pages.php View File

@@ -3,7 +3,9 @@
3 3
 // List of pages and metadata
4 4
 define("PAGES", [
5 5
     "home" => [
6
-        "title" => "home"
6
+        "title" => "home",
7
+        "navbar" => true,
8
+        "icon" => "home"
7 9
     ],
8 10
     "404" => [
9 11
         "title" => "404 error"

+ 14
- 0
settings.template.php View File

@@ -18,6 +18,20 @@ define("SITE_TITLE", "Web App Template");
18 18
 // Used to identify the system in OTP and other places
19 19
 define("SYSTEM_NAME", "Web App Template");
20 20
 
21
+// Which pages to show the app icon on:
22
+// index, app, both, none
23
+define("SHOW_ICON", "both");
24
+// Where to put the icon: top or menu
25
+// Overridden to 'menu' if MENU_BAR_STYLE is 'fixed'.
26
+define("ICON_POSITION", "menu");
27
+// App menu bar style: fixed or static
28
+define("MENU_BAR_STYLE", "fixed");
29
+
30
+// URL of the Business Portal API endpoint
31
+define("PORTAL_API", "http://localhost/api.php");
32
+// Business Portal API Key
33
+define("PORTAL_KEY", "123");
34
+
21 35
 // For supported values, see http://php.net/manual/en/timezones.php
22 36
 define("TIMEZONE", "America/Denver");
23 37
 

BIN
static/img/logo.png View File


+ 78
- 0
static/img/logo.svg View File

@@ -0,0 +1,78 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+<svg
5
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+   xmlns:cc="http://creativecommons.org/ns#"
7
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8
+   xmlns:svg="http://www.w3.org/2000/svg"
9
+   xmlns="http://www.w3.org/2000/svg"
10
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12
+   width="512"
13
+   height="512"
14
+   viewBox="0 0 512.00001 512.00001"
15
+   id="svg2"
16
+   version="1.1"
17
+   inkscape:version="0.91 r13725"
18
+   sodipodi:docname="logo.svg"
19
+   inkscape:export-filename="/home/skylar/Documents/Projects/Sources/WebAppTemplate/static/img/logo.png"
20
+   inkscape:export-xdpi="90"
21
+   inkscape:export-ydpi="90">
22
+  <defs
23
+     id="defs4">
24
+    <inkscape:perspective
25
+       sodipodi:type="inkscape:persp3d"
26
+       inkscape:vp_x="-493.3276 : 245.89848 : 1"
27
+       inkscape:vp_y="0 : 1000 : 0"
28
+       inkscape:vp_z="464.45088 : 245.89848 : 1"
29
+       inkscape:persp3d-origin="-14.438371 : 160.56515 : 1"
30
+       id="perspective4236" />
31
+  </defs>
32
+  <sodipodi:namedview
33
+     id="base"
34
+     pagecolor="#ffffff"
35
+     bordercolor="#666666"
36
+     borderopacity="1.0"
37
+     inkscape:pageopacity="0.0"
38
+     inkscape:pageshadow="2"
39
+     inkscape:zoom="0.49497475"
40
+     inkscape:cx="-135.9681"
41
+     inkscape:cy="352.66131"
42
+     inkscape:document-units="px"
43
+     inkscape:current-layer="layer1"
44
+     showgrid="false"
45
+     units="px" />
46
+  <metadata
47
+     id="metadata7">
48
+    <rdf:RDF>
49
+      <cc:Work
50
+         rdf:about="">
51
+        <dc:format>image/svg+xml</dc:format>
52
+        <dc:type
53
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
54
+        <dc:title></dc:title>
55
+      </cc:Work>
56
+    </rdf:RDF>
57
+  </metadata>
58
+  <g
59
+     inkscape:label="Layer 1"
60
+     inkscape:groupmode="layer"
61
+     id="layer1"
62
+     transform="translate(0,-540.36216)">
63
+    <rect
64
+       style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.74509804"
65
+       id="rect4726"
66
+       width="512"
67
+       height="512"
68
+       x="0"
69
+       y="540.36218"
70
+       rx="50"
71
+       ry="50" />
72
+    <path
73
+       id="path4348"
74
+       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:9.87128067;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
75
+       d="m 132.93564,682.51771 213.96788,-43.14304 0,313.97496 -213.96788,-37.9643 z m 213.96788,-43.14304 0,313.97496 32.16084,-45.18373 0,-217.44396 z m -213.96788,43.14304 213.96788,-43.14304 32.16084,51.34727 -167.21823,22.47784 z m 78.91049,30.68207 167.21823,-22.47784 0,217.44396 -167.21823,-19.77968 z m -78.91049,-30.68207 0,232.86762 78.91049,-26.99911 0,-175.18644 z m 0,232.86762 213.96788,37.9643 32.16084,-45.18373 -167.21823,-19.77968 z"
76
+       inkscape:connector-curvature="0" />
77
+  </g>
78
+</svg>

Loading…
Cancel
Save