├── .github ├── FUNDING.yml └── workflows │ └── deploy_dev.yml ├── .gitignore ├── LICENSE ├── README.md ├── admin ├── account │ ├── index.php │ ├── messages │ │ └── index.php │ └── password │ │ └── index.php ├── backups │ ├── index.php │ ├── settings │ │ └── index.php │ └── system │ │ └── index.php ├── help │ └── index.php ├── index.php ├── menu.php ├── packages │ └── index.php ├── sidebar.php ├── system │ ├── admin │ │ └── index.php │ ├── index.php │ ├── logs │ │ └── index.php │ ├── php │ │ └── index.php │ ├── snp │ │ └── index.php │ └── version │ │ └── index.php └── users │ ├── backups │ └── index.php │ ├── cron-jobs │ └── index.php │ └── index.php ├── api ├── admin │ ├── packages │ │ └── reseller.php │ └── users │ │ ├── admin.php │ │ └── reseller.php ├── auth │ ├── rbac.php │ └── session.php ├── config.php.default ├── controllers │ ├── resellerpackages.controller.php │ └── user.controller.php ├── db.php ├── login │ └── index.php ├── logout.php ├── main.php └── models │ ├── email.php │ ├── name.php │ ├── resellerpackage.php │ ├── role.php │ ├── user.php │ └── usertype.php ├── assets ├── css │ ├── bootstrap.min.css │ ├── panel.css │ └── signin.css ├── fonts │ ├── adlanta.light.otf │ └── encode-sans.condensed.ttf ├── images │ ├── Banner.gif │ ├── icon-lg.gif │ ├── icon-md.gif │ ├── icon-sm.gif │ └── icon-xs.gif └── js │ ├── bootstrap.min.js │ ├── jquery.js │ ├── main.js │ ├── popper.js │ └── toasts.js ├── index.php ├── reseller ├── account │ ├── messages │ │ └── index.php │ ├── password │ │ └── index.php │ └── settings │ │ └── index.php ├── help │ └── index.php ├── index.php ├── menu.php ├── packages │ └── index.php ├── sidebar.php ├── system │ ├── index.php │ ├── logs │ │ └── index.php │ └── settings │ │ └── index.php └── users │ ├── backups │ └── index.php │ ├── index.php │ └── messages │ └── index.php └── user ├── domains └── index.php ├── index-slim.php ├── index.php ├── menu.php └── sidebar.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.paypal.me/tamirslo 13 | -------------------------------------------------------------------------------- /.github/workflows/deploy_dev.yml: -------------------------------------------------------------------------------- 1 | name: Panel Deployment (DEV) 2 | 3 | on: 4 | push: 5 | branches: [ dev ] 6 | 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Deploy Panel (DEV) 12 | uses: appleboy/ssh-action@master 13 | with: 14 | host: ${{secrets.SSH_HOST}} 15 | port: ${{secrets.SSH_PORT}} 16 | username: ${{ secrets.SSH_USER }} 17 | key: ${{ secrets.SSH_KEY }} 18 | script: | 19 | cd ${{ secrets.TARGET_DIR_DEV }} 20 | git pull -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | api/config.php 2 | api/config.php.default 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TS Web Hosting Panel 2 | This project is inspired by DirectAdmin and developed for machines which are not supported and to create an open source, free solution, for Website Hosting on most Linux machines. 3 | 4 | ## Planned Features: 5 | Three access levels: Admin, Reseller and User. 6 | 7 | A rough comparison of features between TS Hosting Panel and DirectAdmin: 8 | 9 | | Permission Level | Feature | TS Panel | DirectAdmin | 10 | | :--------------: | :-----: | :------: | :---------: | 11 | || **SERVER MANAGEMENT** 12 | | Admin | Create Admin | :white_check_mark: | :white_check_mark: | 13 | | Admin | List Admins | :white_check_mark: | :white_check_mark: | 14 | | Admin | Change Passwords | :white_check_mark: | :white_check_mark: | 15 | | Admin | Manage Tickets | :question: | :white_check_mark: | 16 | | Admin | Create Reseller | :white_check_mark: | :white_check_mark: | 17 | | Admin | List Reseller | :white_check_mark: | :white_check_mark: | 18 | | Admin | Manage Reseller Packages | :white_check_mark: | :white_check_mark: | 19 | | Admin | Show All Users | :white_check_mark: | :white_check_mark: | 20 | || **ADMIN TOOLS** 21 | | Admin | IP Managemnet | :x: | :white_check_mark: | 22 | | Admin | DNS Administration | :x: | :white_check_mark: | 23 | | Admin | Admin Backup/Transfer | :white_check_mark: | :white_check_mark: | 24 | | Admin | Multi Server Setup | :x: | :white_check_mark: | 25 | | Admin | Mail Queue Administration | :x: | :white_check_mark: | 26 | | Admin | Move Users Between Resellers | :white_check_mark: | :white_check_mark: | 27 | | Admin | System Information | :question: | :white_check_mark: | 28 | | Admin | Service Monitor | :x: | :white_check_mark: | 29 | | Admin | System Backup | :white_check_mark: | :white_check_mark: | 30 | | Admin | Log Viewer | :white_check_mark: | :white_check_mark: | 31 | | Admin | File Editor | :question: | :white_check_mark: | 32 | | Admin | Process Monitor | :question: | :white_check_mark: | 33 | || **EXTRA FEATURES** 34 | | Admin | Complete Usage Stats. | :x: | :white_check_mark: | 35 | | Admin | Custom HTTPD Config. | :x: | :white_check_mark: | 36 | | Admin | PHP Config. | :white_check_mark: | :white_check_mark: | 37 | | Admin | Brute Force Monitor | :x: | :white_check_mark: | 38 | | Admin | Admin. Settings | :white_check_mark: | :white_check_mark: | 39 | | Admin | Licensing\Updates | :x: \ :white_check_mark: | :white_check_mark: | 40 | | Admin | Plugin Manager | :question: | :white_check_mark: | 41 | | Admin | All User Cron Jobs | :white_check_mark: | :white_check_mark: | 42 | || **ACCOUNT MANAGEMENT** 43 | | Reseller | Add User | :white_check_mark: | :white_check_mark: | 44 | | Reseller | List Users | :white_check_mark: | :white_check_mark: | 45 | | Reseller | Manage Tickets | :question: | :white_check_mark: | 46 | | Reseller | Add Package | :question: | :white_check_mark: | 47 | | Reseller | Manage User Packages | :white_check_mark: | :white_check_mark: | 48 | | Reseller | Edit user Message | :white_check_mark: | :white_check_mark: | 49 | || **RESELLER TOOLS** 50 | | Reseller | Change passwords | :white_check_mark: | :white_check_mark: | 51 | | Reseller | Reseller Stats. | :question: | :white_check_mark: | 52 | | Reseller | IP Management | :x: | :white_check_mark: | 53 | | Reseller | Skin manager | :question: | :white_check_mark: | 54 | | Reseller | Manage User Backups | :white_check_mark: | :white_check_mark: | 55 | || **EXTRA FEATURES** 56 | | Reseller | System Info | :question: | :white_check_mark: | 57 | | Reseller | Nameservers | :x: | :white_check_mark: | 58 | | Reseller | Message All Users | :white_check_mark: | :white_check_mark: | 59 | | Reseller | Contact Administrator | :white_check_mark: | :white_check_mark: | 60 | || **YOUR ACCOUNT** 61 | | User | Domain Setup | :white_check_mark: | :white_check_mark: | 62 | | User | Change Password | :white_check_mark: | :white_check_mark: | 63 | | User | Login History | :question: | :white_check_mark: | 64 | | User | DNS Management | :x: | :white_check_mark: | 65 | | User | Support Center | :question: | :white_check_mark: | 66 | | User | Installed Perl Modules | :question: | :white_check_mark: | 67 | | User | Create\Restore Backups | :white_check_mark: | :white_check_mark: | 68 | | User | Site Summary \ Stats. \ Logs | :question: | :white_check_mark: | 69 | | User | FTP Management | :white_check_mark: | :white_check_mark: | 70 | | User | Subdomain Management | :white_check_mark: | :white_check_mark: | 71 | | User | MySQLManagement | :white_check_mark: | :white_check_mark: | 72 | | User | Password Protected Directories | :question: | :white_check_mark: | 73 | | User | File Manager | :question: | :white_check_mark: | 74 | || **E-MAIL MANAGEMENT** 75 | | User | E-Mail Accounts | :x: | :white_check_mark: | 76 | | User | Catch-All Email | :x: | :white_check_mark: | 77 | | User | Forwarders | :x: | :white_check_mark: | 78 | | User | Autoresponders | :x: | :white_check_mark: | 79 | | User | Vacation Messages | :x: | :white_check_mark: | 80 | | User | Spamassassin Setup | :x: | :white_check_mark: | 81 | | User | Mailing Lists | :x: | :white_check_mark: | 82 | | User | SPAM Filters | :x: | :white_check_mark: | 83 | | User | Webmail: Sq. | :x: | :white_check_mark: | 84 | | User | Webmail: RC | :x: | :white_check_mark: | 85 | | User | MX Records | :x: | :white_check_mark: | 86 | || **ADVANCED FEATURES** 87 | | User | Server Info. | :question: | :white_check_mark: | 88 | | User | SSL Certs. | :white_check_mark: | :white_check_mark: | 89 | | User | Cronjobs | :question: | :white_check_mark: | 90 | | User | Mime Types | :x: | :white_check_mark: | 91 | | User | Apache Handlers | :x: | :white_check_mark: | 92 | | User | SSH Keys | :x: | :white_check_mark: | 93 | | User | Custom Error Pages | :white_check_mark: | :white_check_mark: | 94 | | User | phpMyAdmin | :white_check_mark: | :white_check_mark: | 95 | | User | Site Redirection | :white_check_mark: | :white_check_mark: | 96 | | User | Domain Pointers | :x: | :white_check_mark: | 97 | | User | Login Keys | :question: | :white_check_mark: | 98 | 99 | 100 | **_A Messaging / Tickets system will also be implemented at a later stage of the development. Email managemnet is not planned to be included within this Web Hosting Panel as no experience with such systems. A later assessment will be performed and it could be added at a later stage with no complications._** 101 | 102 | ###### This is an ongoing project that is actively being modified. This is developed privately, and not widely tested. 103 | 104 | ## Copyright 105 | This project is licensed with the GNU General Public License. 106 | -------------------------------------------------------------------------------- /admin/account/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Settings

14 | 15 | footer(); 17 | ?> 18 | -------------------------------------------------------------------------------- /admin/account/messages/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Messages

14 | 15 | footer(); 17 | ?> 18 | -------------------------------------------------------------------------------- /admin/account/password/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Password

14 | 15 | footer(); 17 | ?> 18 | -------------------------------------------------------------------------------- /admin/backups/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Backups

14 |
15 |
16 |

Backups List

17 |
18 | 19 |
20 |

21 | 22 |
23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 43 |
WhenWhoWhereWhatActions
20/06/2020All Users/usr/backupsAll Data 39 | 40 | 41 |
44 |
45 |
46 | 47 | 148 | 149 | footer(); 151 | ?> 152 | -------------------------------------------------------------------------------- /admin/backups/settings/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Backup Settings

14 | 15 |
16 |
17 |

Who to backup?

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 |

32 |
33 | 34 | 35 |

36 |
37 | 38 | 39 |

40 |
41 |
42 |
43 |
44 | 45 |
46 |
47 |

When to backup?

48 |
49 | 50 |
51 |

52 | 53 |
54 |
55 |
56 |
57 |
58 |
59 | 60 | 61 |

62 |
63 | 64 | 65 |

66 |
67 |
68 |
69 |
70 | 71 |
72 |
73 |

Where to backup?

74 |
75 | 76 |
77 |

78 | 79 |
80 |
81 |
82 |
83 |
84 |
85 | 86 | 87 |

88 | 89 | 90 |
91 |
92 | 93 | 94 |

95 |
96 | 97 | 98 |
99 |
100 |
101 |
102 |
103 | 104 |
105 |
106 |

What to backup?

107 |
108 | 109 |
110 |

111 | 112 |
113 |
114 |
115 |
116 |
117 |
118 | 119 | 120 |

121 |
122 | 123 | 124 |

125 |
126 |
127 |
128 |
129 | 130 | footer(); 132 | ?> 133 | -------------------------------------------------------------------------------- /admin/backups/system/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

System Backups

14 |
15 |
16 |

System Backups List

17 |
18 | 19 |
20 |

21 | 22 |
23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 |
WhenWhereActions
20/06/2020/root/backups 35 | 36 | 37 |
40 |
41 |
42 | 43 | 107 | 108 | footer(); 110 | ?> 111 | -------------------------------------------------------------------------------- /admin/help/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 | 13 |

Help

14 | 15 |
16 |
17 | How can I create a new user? 18 |
19 |
20 |

Example

21 | Users 22 |
23 |
24 | 25 | footer(); 27 | ?> 28 | 29 | -------------------------------------------------------------------------------- /admin/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | ?> 12 |

Dashboard

13 | 14 | 15 |
16 |

Admin Summary

17 |
18 |
19 |
20 | Resellers 21 |
22 |
2 (3)
23 |
24 |
25 |
26 | Users 27 |
28 |
2 (10)
29 |
30 |
31 |
32 | Domains 33 |
34 |
1 (∞)
35 |
36 |
37 |
38 | Databases 39 |
40 |
1 (∞)
41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |

Server Summary

49 |
50 |
51 |
52 | Disk Usage 53 |
54 |
2 (3)
55 |
56 |
57 |
58 | Bandwidth 59 |
60 |
2 (10)
61 |
62 |
63 |
64 |
65 |
66 | 67 |
68 |

Active Tickets

69 |
70 | No Active Tickets were found. 71 |
72 |
73 | 74 |
75 |

New Messages

76 |
77 | You have no new messages. 78 |
79 |
80 | 81 | footer(); 83 | ?> 84 | -------------------------------------------------------------------------------- /admin/menu.php: -------------------------------------------------------------------------------- 1 | user->FName; 6 | $lname = $tshp->user->LName; 7 | 8 | ?> 9 | 10 | -------------------------------------------------------------------------------- /admin/packages/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 4 | 5 | $tshp = TSHP::getInstance(); 6 | 7 | $ui = new UI(); 8 | 9 | $ui->headerAdmin(); 10 | $resellerPackages = $tshp->resellerPackages->selectAll(); 11 | 12 | ?> 13 | 14 |

Reseller Packages

15 |
16 |
17 |

Packages List

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | There are no Reseller Packages within this Web Hosting Panel yet... Add a package here 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 |
Package NameBandwidthDisk UsageUsersDomainsDatabasesActions
Name; ?>MaxBandwidth; ?>MBMaxDiskUsage; ?>MBMaxUsers; ?>MaxDomains; ?>MaxDatabases; ?> 48 | 49 | 50 |
54 | 55 |
56 |
57 | 58 | 59 | 60 | 61 | 62 | 137 | 138 | footer(); 140 | ?> 141 | -------------------------------------------------------------------------------- /admin/sidebar.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /admin/system/admin/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Admin Settings

15 | 16 | footer(); 18 | ?> 19 | -------------------------------------------------------------------------------- /admin/system/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

System Information

15 |
16 |
17 |

General

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
UptimeCPUs Count
05:00:282
36 |
37 |
38 | 39 |
40 |
41 |

CPUs Information

42 |
43 | 44 |
45 |

46 | 47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
Processor NameVendor IDProcessor Speed (MHz)
Example 2Try4
62 |
63 |
64 | 65 |
66 |
67 |

Memory Information

68 |
69 | 70 |
71 |

72 | 73 |
74 |
75 |
76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
Total MemoryFree MemoryAvailable MemoryTotal Swap MemoryFree Swap MemoryCached Swap Memory
640 KB12KB0 B0 B0 B0 B
94 |
95 |
96 | 97 |
98 |
99 |

Load Average

100 |
101 | 102 |
103 |

104 | 105 |
106 |
107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
1 minute10 minutes25 minutes
0.90.40.25
120 |
121 |
122 | 123 | footer(); 125 | ?> 126 | -------------------------------------------------------------------------------- /admin/system/logs/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Logs

15 |
16 | Please select a log file to view: 17 | 27 |
28 | 29 |
30 | Options: 31 | 32 |
33 | 34 | footer(); 36 | ?> 37 | -------------------------------------------------------------------------------- /admin/system/php/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

PHP Settings

15 | 16 | footer(); 18 | ?> 19 | -------------------------------------------------------------------------------- /admin/system/snp/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Services and Processes

15 |
16 |
17 |

Services

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
TSHPApacheMySQLphpsshd
StateStateStateStateState
1.20.50.6.20.1.10.0.1.5
49 |
50 |
51 | 52 | footer(); 54 | ?> 55 | -------------------------------------------------------------------------------- /admin/system/version/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Panel Information

15 |
16 |
17 |

General

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
NameVersionLicenseLast Updated
TSHP0.1.1Verified by TSHP18/12/2021
40 |
41 |
42 | 43 | footer(); 45 | ?> 46 | -------------------------------------------------------------------------------- /admin/users/backups/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Manage Backups

15 |
16 |
17 |

Users

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
IDUserDateLocationOptions
2Example27/05/2018home/backups
42 |
43 |
44 | 45 | footer(); 47 | ?> 48 | -------------------------------------------------------------------------------- /admin/users/cron-jobs/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerAdmin(); 11 | 12 | ?> 13 | 14 |

Manage Cron Jobs

15 |
16 |
17 |

Users

18 |
19 | 20 | 21 |
22 |

23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
IDUserMinuteHourDay of MonthMonthDay of WeekCommand
1Example5102652home/demo/run
50 |
51 |
52 | 53 | footer(); 55 | ?> 56 | -------------------------------------------------------------------------------- /api/admin/packages/reseller.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 4 | 5 | $tshp = TSHP::getInstance(); 6 | 7 | if(isset($_POST['Name'])){ 8 | $r = $tshp->resellerPackages->create($_POST); 9 | echo json_encode(array("success" => true, "message" => "Reseller Package created successfully!", "data" => $r)); 10 | }else{ 11 | http_response_code(405); // METHOD NOT ALLOWED 12 | echo json_encode(array("success"=>false,"error"=>"Method not allowed")); 13 | } 14 | ?> -------------------------------------------------------------------------------- /api/admin/users/admin.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | if(isset($_GET['id'])){ 9 | $id = $_GET['id']; 10 | $user = $tshp->users->getUserByID($id); 11 | echo json_encode(array("success"=>true,"data"=>$user)); 12 | }else if(isset($_POST['Username'])){ 13 | $user = $_POST['Username']; 14 | $pass = $_POST['Password']; 15 | $email = $_POST['Email']; 16 | $fname = $_POST['FName']; 17 | $lname = $_POST['LName']; 18 | $welcomemail = false; 19 | if(isset($_POST['UserID']) && $_POST['UserID'] != ""){ 20 | $userid = $_POST['UserID']; 21 | $r = $tshp->users->getUserByID($userid)->edit( 22 | new Models\Name($user), 23 | $pass, 24 | new Models\Email($email), 25 | new Models\Name($fname), 26 | new Models\Name($lname), 27 | Models\UserType::Admin(), 28 | null 29 | ); 30 | }else{ 31 | $r = $tshp->users->create($_POST, Models\UserType::Admin()); 32 | } 33 | echo json_encode(array("success"=>true,"data"=>$r,"message"=>"Successfully saved admin.")); 34 | }else if(isset($_POST['delete'])){ 35 | $id = $_POST['delete']; 36 | $r = $tshp->users->deleteByID($id); 37 | echo json_encode(array("success"=>$r)); 38 | }else{ 39 | http_response_code(405); // METHOD NOT ALLOWED 40 | echo json_encode(array("success"=>false,"error"=>"Method not allowed")); 41 | } 42 | ?> -------------------------------------------------------------------------------- /api/admin/users/reseller.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | if(isset($_GET['id'])){ 9 | $id = $_GET['id']; 10 | $user = $tshp->users->getUserByID($id); 11 | echo json_encode(array("success"=>true,"data"=>$user)); 12 | }else if(isset($_POST['Username'])){ 13 | $user = $_POST['Username']; 14 | $pass = $_POST['Password']; 15 | $email = $_POST['Email']; 16 | $fname = $_POST['FName']; 17 | $lname = $_POST['LName']; 18 | $package = $_POST['Package']; 19 | $welcomemail = false; 20 | if(isset($_POST['UserID']) && $_POST['UserID'] != ""){ 21 | $userid = $_POST['UserID']; 22 | $r = $tshp->users->getUserByID($userid)->edit( 23 | new Models\Name($user), 24 | $pass, 25 | new Models\Email($email), 26 | new Models\Name($fname), 27 | new Models\Name($lname), 28 | Models\UserType::Reseller(), 29 | $package 30 | ); 31 | }else{ 32 | $r = $tshp->users->create($_POST, Models\UserType::Reseller()); 33 | } 34 | echo json_encode(array("success"=>true,"data"=>$r,"message"=>"Successfully saved reseller.")); 35 | }else if(isset($_POST['delete'])){ 36 | $id = $_POST['delete']; 37 | $r = $tshp->users->deleteByID($id); 38 | echo json_encode(array("success"=>$r)); 39 | }else{ 40 | http_response_code(405); // METHOD NOT ALLOWED 41 | echo json_encode(array("success"=>false,"error"=>"Method not allowed")); 42 | } 43 | ?> -------------------------------------------------------------------------------- /api/auth/rbac.php: -------------------------------------------------------------------------------- 1 | user->UserType->getRole(); 14 | 15 | if($role == Role::Admin){ 16 | return; // Admin can do everything 17 | } 18 | 19 | $category = explode('.',$perm)[0]; 20 | $action = explode('.',$perm)[1]; 21 | 22 | if(@gettype(((object) self::$$category)->$action) == 'array'){ 23 | $allowedRoles = ((object) self::$$category)->$action; 24 | } 25 | else throw new \Exception("Permission not found."); 26 | 27 | in_array($role, $allowedRoles) || throw new \Exception("Unauthorized"); 28 | 29 | 30 | if($category == "users"){ 31 | if($role == Role::Reseller){ 32 | if($otherID != null && $tshp->user->UserID != $otherID){ 33 | $user = User::selectByID($otherID); 34 | if($user->ResellerID != $tshp->user->UserID){ 35 | throw new \Exception("Unauthorized"); 36 | } 37 | } 38 | } 39 | 40 | if($role == Role::User){ 41 | if($otherID != null && $tshp->user->UserID != $otherID){ 42 | throw new \Exception("Unauthorized"); 43 | } 44 | } 45 | } 46 | } 47 | 48 | public static array $users = [ 49 | "create" => [Role::Reseller], 50 | "read" => [Role::Reseller, Role::User], 51 | "update" => [Role::Reseller, Role::User], 52 | "delete" => [Role::Reseller], 53 | ]; 54 | 55 | public static array $resellerPackages = [ 56 | "create" => [], 57 | "read" => [Role::Reseller], 58 | "update" => [], 59 | "delete" => [], 60 | ]; 61 | 62 | } 63 | 64 | ?> -------------------------------------------------------------------------------- /api/auth/session.php: -------------------------------------------------------------------------------- 1 | Authenticate(); 12 | $url = $_SERVER['REQUEST_URI']; 13 | 14 | if($user->Admin){ 15 | if (!strpos($url,'admin') && !strpos($url,'reseller') && !strpos($url,'user') && !strpos($url,'api')) header("Location:/admin/"); 16 | } else if($user->Reseller) { 17 | if (!strpos($url,'reseller') && !strpos($url,'user') && !strpos($url,'api')) header("Location:/reseller/"); 18 | } else { 19 | if (!strpos($url,'user') && !strpos($url,'api')) header("Location:/user/"); 20 | } 21 | 22 | $this->user = $user; 23 | }catch(\Exception $e){ 24 | switch ($_SERVER['REQUEST_URI']) { 25 | case '/': 26 | break; 27 | case '/api/login/': 28 | break; 29 | default: 30 | setcookie("error",str_replace(' ','%20',"You are not authorised to view this page... Please login."),0,"/"); 31 | setcookie("eRefferal",$_SERVER['REQUEST_URI'],0,"/"); 32 | header("Location:/"); 33 | 34 | } 35 | } 36 | } 37 | 38 | private function Authenticate(): \API\Models\User { 39 | if(isset($_SESSION['Username']) && isset($_SESSION['Password'])) { 40 | $db = \API\DB::getInstance(); 41 | $username = $_SESSION['Username']; 42 | $pass = $_SESSION['Password']; 43 | 44 | $auth = $db->Login($username); 45 | if($auth['success'] && count($auth['results']) > 0){ 46 | $dbpass = $auth["results"][0]['Password']; 47 | 48 | if($pass == $dbpass) { 49 | 50 | $user = \API\Models\User::selectByUsername($username); 51 | if($user->Suspended){ 52 | throw new \Exception("Your account has been suspended."); 53 | } 54 | 55 | return $user; 56 | } 57 | } 58 | } 59 | throw new \Exception("Session expired."); 60 | } 61 | 62 | public static function Login(\API\Models\Name $username, string $pass): string { 63 | $db = \API\DB::getInstance(); 64 | $auth = $db->Login($username); 65 | 66 | if($auth['success'] && count($auth['results']) > 0){ 67 | $dbpassword = $auth["results"][0]['Password']; 68 | $dbsalt = $auth["results"][0]['Salt']; 69 | 70 | $hpass = self::hashPass($pass,$dbsalt); 71 | 72 | if($dbpassword == $hpass){ 73 | $user = \API\Models\User::selectByUsername($username); 74 | if($user->Suspended){ 75 | throw new \Exception("Your account has been suspended."); 76 | } 77 | 78 | $_SESSION['Username'] = $username; 79 | $_SESSION['Password'] = $dbpassword; 80 | 81 | return strtolower($user->UserType)."/"; 82 | } 83 | } 84 | throw new \Exception("Invalid details. Please verify your Username and Password"); 85 | } 86 | 87 | public static function generateSalt(): string{ 88 | $bytes = random_bytes(16); 89 | $salt = bin2hex($bytes); 90 | return $salt; 91 | } 92 | 93 | public static function hashPass(string $password, string $salt): string{ 94 | $p_md5 = hash("sha256", $password); 95 | $s_sha1 = hash("sha256", $salt); 96 | $pns = $p_md5 . $s_sha1; 97 | $hashed = hash("sha256", $pns); 98 | return $hashed; 99 | } 100 | 101 | public static function Logout(){ 102 | session_destroy(); 103 | } 104 | } 105 | 106 | 107 | ?> -------------------------------------------------------------------------------- /api/config.php.default: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/controllers/resellerpackages.controller.php: -------------------------------------------------------------------------------- 1 | create(); 21 | } 22 | } -------------------------------------------------------------------------------- /api/controllers/user.controller.php: -------------------------------------------------------------------------------- 1 | user->UserID == $id){ 26 | throw new \Exception("You cannot delete yourself"); 27 | } 28 | 29 | $user = User::selectByID($id); 30 | if($user->UserType->isAdmin() && $user->UserCount > 0){ 31 | throw new \Exception("You cannot delete an admin with users"); 32 | } 33 | if($user->UserType->isReseller() && $user->UserCount > 0){ 34 | throw new \Exception("You cannot delete a reseller with users"); 35 | } 36 | 37 | $user->delete(); 38 | return true; 39 | } 40 | 41 | public function selectAll(): Users{ 42 | RBAC::checkPerms("users.read", null); 43 | 44 | return User::selectAll(); 45 | } 46 | 47 | public function create(array $dbUser, UserType $userType): User{ 48 | $tshp = \API\TSHP::getInstance(); 49 | RBAC::checkPerms("users.create", null); 50 | 51 | if($tshp->user->Reseller && $userType->isNotUser()){ 52 | throw new \Exception('You cannot create users of this type'); 53 | } 54 | 55 | $dbUser['UserID'] = 0; 56 | $user = User::dbUserToObject([ 57 | ...$dbUser, 58 | 'UserCount' => 0, 59 | 'Suspended' => 0, 60 | 'Admin' => $userType->isAdmin(), 61 | 'Reseller' => $userType->isReseller(), 62 | 'ResellerID' => $tshp->user->UserID, 63 | 'ResellerPackageID' => $dbUser['ResellerPackageID'] ?? null]); 64 | $user->UserType = $userType; 65 | 66 | $emailExists = false; 67 | try{ 68 | User::selectByEmail($user->Email); 69 | $emailExists = true; 70 | }catch(\Exception $e){ 71 | // Do nothing 72 | }finally{ 73 | if($emailExists){ 74 | throw new \Exception('Email already exists'); 75 | } 76 | } 77 | 78 | $usernameExists = false; 79 | try{ 80 | User::selectByUsername($user->Username); 81 | $usernameExists = true; 82 | }catch(\Exception $e){ 83 | // Do nothing 84 | }finally{ 85 | if($usernameExists){ 86 | throw new \Exception('Username already exists'); 87 | } 88 | } 89 | 90 | try{ 91 | if($userType->isReseller()){ 92 | if($user->ResellerPackageID) ResellerPackage::selectByID($user->ResellerPackageID); 93 | else throw new \Exception('Reseller package not selected'); 94 | }elseif($userType->isUser()){ 95 | // TODO: Check for UserPackageID 96 | if($user->ResellerID) User::selectByID($user->ResellerID); 97 | else throw new \Exception('Reseller not selected'); 98 | } 99 | }catch(\Exception $e){ 100 | throw $e; 101 | } 102 | 103 | return $user->create($dbUser['Password']); 104 | } 105 | } 106 | 107 | 108 | 109 | ?> -------------------------------------------------------------------------------- /api/db.php: -------------------------------------------------------------------------------- 1 | host = $h; 19 | $this->username = $u; 20 | $this->password = $p; 21 | $this->dbname = $d; 22 | } 23 | 24 | public static function getInstance(): DB 25 | { 26 | if (self::$instance == null) { 27 | if(!@include("config.php")) die("Error 3 -> Couldn't require Configuration."); 28 | self::$instance = new DB($config['db_host'],$config['db_user'],$config['db_pass'],$config['db_name']); 29 | self::$instance->connect(); 30 | return self::$instance; 31 | }else{ 32 | return self::$instance; 33 | } 34 | } 35 | 36 | public function connect() 37 | { 38 | try { 39 | $this->db = new PDO('mysql:host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password); 40 | $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 41 | return true; 42 | } catch (PDOException $e) { 43 | error_log('PDOException - ' . $e->getMessage(), 0); 44 | http_response_code(500); 45 | die('Error establishing connection with database'); 46 | } 47 | } 48 | 49 | private function checkResponse($r, $sql = "SEL", $s = true){ // $r = a PDOStatement Object, $sql = type of statement [SEL,INS,UPD,DEL]; 50 | if ($sql == "SEL"){ 51 | $r->setFetchMode(PDO::FETCH_ASSOC); 52 | $success = $r->execute(); 53 | $arr = $r->fetchAll(); 54 | if(!$success) { 55 | return array("success" => false, "error" => "Error in SQL Response"); 56 | }else{ 57 | return array("success" => true, "results" => $arr); 58 | } 59 | } 60 | 61 | if ($sql == "INS" || $sql == "UPD" || $sql == "DEL"){ 62 | if($s){ 63 | return array("success" => true); 64 | }else{ 65 | try { 66 | $r->setFetchMode(PDO::FETCH_ASSOC); 67 | $s = $r->execute(); 68 | } catch (PDOException $e) { 69 | error_log('PDOException - ' . $e->getMessage(), 0); 70 | } 71 | } 72 | if(!$s) { 73 | return array("success" => false, "error" => "Error in SQL Response"); 74 | }else{ 75 | return array("success" => true); 76 | } 77 | } 78 | } 79 | 80 | public function Login($user){ 81 | try { 82 | $query = "SELECT Salt, Password, Suspended FROM users WHERE Username = ?"; 83 | $st = $this->db->prepare($query); 84 | //$st->bindParam('?', $user); 85 | $st->setFetchMode(PDO::FETCH_ASSOC); 86 | $st->execute(array($user)); 87 | } catch (PDOException $e) { 88 | error_log('PDOException - ' . $e->getMessage(), 0); 89 | } 90 | return $this->checkResponse($st); 91 | } 92 | 93 | public function addUser($user,$hpass,$salt,$email,$fname,$lname,$admin,$reseller,$resellerPackageID){ 94 | try { 95 | $query = "INSERT INTO users (Username, Password, Salt, Email, FName, LName, Admin, Reseller, ResellerPackageID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; 96 | $st = $this->db->prepare($query); 97 | //$st->bindParam('?', $user); 98 | $st->setFetchMode(PDO::FETCH_ASSOC); 99 | $s = $st->execute(array($user,$hpass,$salt,$email,$fname,$lname,$admin,$reseller,$resellerPackageID)); 100 | } catch (PDOException $e) { 101 | error_log('PDOException - ' . $e->getMessage(), 0); 102 | } 103 | return $this->checkResponse($st, "INS", $s); 104 | } 105 | 106 | public function editUser($id,$user,$email,$fname,$lname,$admin,$reseller,$resellerPackageID){ 107 | try { 108 | $query = "UPDATE users SET Username = ?, Email = ?, FName = ?, LName = ?, Admin = ?, Reseller = ?, ResellerPackageID = ? WHERE UserID = ?"; 109 | $st = $this->db->prepare($query); 110 | //$st->bindParam('?', $user); 111 | $st->setFetchMode(PDO::FETCH_ASSOC); 112 | $s = $st->execute(array($user,$email,$fname,$lname,$admin,$reseller,$resellerPackageID,$id)); 113 | } catch (PDOException $e) { 114 | error_log('PDOException - ' . $e->getMessage(), 0); 115 | } 116 | return $this->checkResponse($st, "UPD", $s); 117 | } 118 | 119 | public function editUserPassword($id,$hpass,$salt){ 120 | try { 121 | $query = "UPDATE users SET Password = ?, Salt = ? WHERE UserID = ?"; 122 | $st = $this->db->prepare($query); 123 | //$st->bindParam('?', $user); 124 | $st->setFetchMode(PDO::FETCH_ASSOC); 125 | $s = $st->execute(array($hpass,$salt,$id)); 126 | } catch (PDOException $e) { 127 | error_log('PDOException - ' . $e->getMessage(), 0); 128 | } 129 | return $this->checkResponse($st, "UPD", $s); 130 | } 131 | 132 | public function addResellerPackage($name,$users,$bandwidth,$diskSpace,$domains,$subDomains,$databases,$ftpAccounts){ 133 | try { 134 | $query = "INSERT INTO packages_reseller (Name, MaxUsers, MaxBandwidth, MaxDiskUsage, MaxDomains, MaxSubDomains, MaxDatabases, MaxFTPAccounts) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; 135 | $st = $this->db->prepare($query); 136 | //$st->bindParam('?', $user); 137 | $st->setFetchMode(PDO::FETCH_ASSOC); 138 | $s = $st->execute(array($name,$users,$bandwidth,$diskSpace,$domains,$subDomains,$databases,$ftpAccounts)); 139 | } catch (PDOException $e) { 140 | error_log('PDOException - ' . $e->getMessage(), 0); 141 | } 142 | return $this->checkResponse($st, "INS", $s); 143 | } 144 | 145 | public function getUserByID($id){ 146 | try { 147 | $query = "SELECT *, (SELECT COUNT(*) FROM users b WHERE a.UserID=b.ResellerID) as UserCount FROM users a WHERE UserID = ?"; 148 | $st = $this->db->prepare($query); 149 | //$st->bindParam('?', $user); 150 | $st->setFetchMode(PDO::FETCH_ASSOC); 151 | $st->execute(array($id)); 152 | } catch (PDOException $e) { 153 | error_log('PDOException - ' . $e->getMessage(), 0); 154 | } 155 | return $this->checkResponse($st); 156 | } 157 | 158 | public function deleteUserByID($id){ 159 | try { 160 | $query = "DELETE FROM users WHERE UserID = ?"; 161 | $st = $this->db->prepare($query); 162 | //$st->bindParam('?', $user); 163 | $st->setFetchMode(PDO::FETCH_ASSOC); 164 | $s = $st->execute(array($id)); 165 | } catch (PDOException $e) { 166 | error_log('PDOException - ' . $e->getMessage(), 0); 167 | } 168 | return $this->checkResponse($st, "DEL", $s); 169 | } 170 | 171 | public function getUserDetails($user){ 172 | try { 173 | $query = "SELECT *, (SELECT COUNT(*) FROM users b WHERE a.UserID=b.ResellerID) as UserCount FROM users a WHERE Username = ?"; 174 | $st = $this->db->prepare($query); 175 | //$st->bindParam('?', $user); 176 | $st->setFetchMode(PDO::FETCH_ASSOC); 177 | $st->execute(array($user)); 178 | } catch (PDOException $e) { 179 | error_log('PDOException - ' . $e->getMessage(), 0); 180 | } 181 | return $this->checkResponse($st); 182 | } 183 | 184 | public function getEmailDetails($email){ 185 | try { 186 | $query = "SELECT *, (SELECT COUNT(*) FROM users b WHERE a.UserID=b.ResellerID) as UserCount FROM users a WHERE Email = ?"; 187 | $st = $this->db->prepare($query); 188 | //$st->bindParam('?', $user); 189 | $st->setFetchMode(PDO::FETCH_ASSOC); 190 | $st->execute(array($email)); 191 | } catch (PDOException $e) { 192 | error_log('PDOException - ' . $e->getMessage(), 0); 193 | } 194 | return $this->checkResponse($st); 195 | } 196 | 197 | public function getAllUsers(){ 198 | try { 199 | $query = "SELECT a.UserID, a.Username, a.Email, a.FName, a.LName, a.Suspended, a.Admin, a.Reseller, a.ResellerID, a.ResellerPackageID, (SELECT COUNT(*) FROM users b WHERE a.UserID=b.ResellerID) as UserCount FROM users a ORDER BY a.UserID ASC"; 200 | $st = $this->db->prepare($query); 201 | //$st->bindParam('?', $user); 202 | $st->setFetchMode(PDO::FETCH_ASSOC); 203 | $st->execute(); 204 | } catch (PDOException $e) { 205 | error_log('PDOException - ' . $e->getMessage(), 0); 206 | } 207 | return $this->checkResponse($st); 208 | } 209 | 210 | public function getUsersOfReseller($resellerID){ 211 | try { 212 | $query = "SELECT a.UserID, a.Username, a.Email, a.FName, a.LName, a.Suspended, a.ResellerID FROM users a WHERE a.ResellerID = ? ORDER BY a.UserID ASC;"; 213 | $st = $this->db->prepare($query); 214 | //$st->bindParam('?', $user); 215 | $st->setFetchMode(PDO::FETCH_ASSOC); 216 | $st->execute(array($resellerID)); 217 | } catch (PDOException $e) { 218 | error_log('PDOException - ' . $e->getMessage(), 0); 219 | } 220 | return $this->checkResponse($st); 221 | } 222 | 223 | public function getResellerPackages(){ 224 | try { 225 | $query = "SELECT * FROM packages_reseller"; 226 | $st = $this->db->prepare($query); 227 | //$st->bindParam('?', $user); 228 | $st->setFetchMode(PDO::FETCH_ASSOC); 229 | $st->execute(); 230 | } catch (PDOException $e) { 231 | error_log('PDOException - ' . $e->getMessage(), 0); 232 | } 233 | return $this->checkResponse($st); 234 | } 235 | 236 | public function getResellerPackageByID($id){ 237 | try { 238 | $query = "SELECT * FROM packages_reseller WHERE ResellerPackageID = ?"; 239 | $st = $this->db->prepare($query); 240 | //$st->bindParam('?', $user); 241 | $st->setFetchMode(PDO::FETCH_ASSOC); 242 | $st->execute(array($id)); 243 | } catch (PDOException $e) { 244 | error_log('PDOException - ' . $e->getMessage(), 0); 245 | } 246 | return $this->checkResponse($st); 247 | } 248 | 249 | public function deleteResellerPackageById($id){ 250 | try { 251 | $query = "DELETE FROM packages_reseller WHERE ResellerPackageID = ?"; 252 | $st = $this->db->prepare($query); 253 | //$st->bindParam('?', $user); 254 | $st->setFetchMode(PDO::FETCH_ASSOC); 255 | $s = $st->execute(array($id)); 256 | } catch (PDOException $e) { 257 | error_log('PDOException - ' . $e->getMessage(), 0); 258 | } 259 | return $this->checkResponse($st, "DEL", $s); 260 | } 261 | 262 | public function updatePackageOfReseller($resellerID, $packageID){ 263 | try { 264 | $query = "UPDATE users SET ResellerPackageID = ? WHERE UserID = ?"; 265 | $st = $this->db->prepare($query); 266 | //$st->bindParam('?', $user); 267 | $st->setFetchMode(PDO::FETCH_ASSOC); 268 | $s = $st->execute(array($packageID, $resellerID)); 269 | } catch (PDOException $e) { 270 | error_log('PDOException - ' . $e->getMessage(), 0); 271 | } 272 | return $this->checkResponse($st, "UPD", $s); 273 | } 274 | 275 | public function updatePackageOfUser($userID, $packageID){ 276 | try { 277 | $query = "UPDATE users SET UserPackageID = ? WHERE UserID = ?"; 278 | $st = $this->db->prepare($query); 279 | //$st->bindParam('?', $user); 280 | $st->setFetchMode(PDO::FETCH_ASSOC); 281 | $s = $st->execute(array($packageID, $userID)); 282 | } catch (PDOException $e) { 283 | error_log('PDOException - ' . $e->getMessage(), 0); 284 | } 285 | return $this->checkResponse($st, "UPD", $s); 286 | } 287 | 288 | public function lastInsertId(){ 289 | $id = $this->db->lastInsertId(); 290 | return $id; 291 | } 292 | 293 | } 294 | 295 | ?> -------------------------------------------------------------------------------- /api/login/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | use API\Auth\Session; 9 | 10 | if(isset($_POST['username'])){ 11 | $user = $_POST['username']; 12 | $pass = $_POST['password']; 13 | $r = Session::Login(new \API\Models\Name($user),$pass); 14 | echo json_encode(array("success"=>true,"redirect"=>$r)); 15 | }else{ 16 | http_response_code(405); // METHOD NOT ALLOWED 17 | echo json_encode(array("success"=>false,"error"=>"Method not allowed")); 18 | } 19 | ?> -------------------------------------------------------------------------------- /api/logout.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 7 | 8 | $tshp = TSHP::getInstance(); 9 | 10 | Session::logout(); 11 | die(json_encode(array("success" => true))); 12 | 13 | ?> -------------------------------------------------------------------------------- /api/main.php: -------------------------------------------------------------------------------- 1 | false, 35 | "error" => $e->getMessage() 36 | ]); 37 | }); 38 | 39 | $this->db = DB::getInstance(); 40 | 41 | $session = new Session(); 42 | $this->user = $session->user ?? null; 43 | 44 | $this->users = new UserController(); 45 | $this->resellerPackages = new ResellerPackagesController(); 46 | 47 | } 48 | 49 | public static function getInstance(): self{ 50 | if(!isset(self::$instance)){ 51 | self::$instance = new self(); 52 | } 53 | return self::$instance; 54 | } 55 | } 56 | 57 | 58 | 59 | 60 | 61 | // ======================= U S E R I N T E R F A C E C L A S S ======================= \\ 62 | 63 | class UI{ 64 | 65 | public function header(){ 66 | echo ' 67 | 68 | TS Hosting Panel 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
83 | 84 | 85 | '; 86 | if(!@include(dirname(__FILE__)."/../user/menu.php")) die("Error 5 -> Couldn't require menu."); 87 | echo '
'; 88 | if(!@include(dirname(__FILE__)."/../user/sidebar.php")) die("Error 6 -> Couldn't require sidebar."); 89 | echo '
'; 90 | } 91 | 92 | public function headerReseller(){ 93 | echo ' 94 | 95 | TS Hosting Panel 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 |
110 | 111 | 112 | '; 113 | if(!@include(dirname(__FILE__)."/../reseller/menu.php")) die("Error 5 -> Couldn't require menu."); 114 | echo '
'; 115 | if(!@include(dirname(__FILE__)."/../reseller/sidebar.php")) die("Error 6 -> Couldn't require sidebar."); 116 | echo '
'; 117 | } 118 | 119 | public function headerAdmin(){ 120 | echo ' 121 | 122 | TS Hosting Panel 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
137 | 138 | 139 | '; 140 | if(!@include(dirname(__FILE__)."/../admin/menu.php")) die("Error 5 -> Couldn't require menu."); 141 | echo '
'; 142 | if(!@include(dirname(__FILE__)."/../admin/sidebar.php")) die("Error 6 -> Couldn't require sidebar."); 143 | echo '
'; 144 | } 145 | 146 | public function footer(){ 147 | echo '
'; 148 | $this->copyright(false); 149 | echo '
'; 150 | echo ' 151 |
152 |
153 |
154 |
'; 155 | } 156 | 157 | public function copyright($phone = true){ 158 | $year = date('Y'); 159 | $first = "© 2021 - " . $year ." Web Hosting Panel - Developed by "; 160 | $tamir = 'TamirSlo'; 161 | if(!$phone){ 162 | echo '
163 | '.$first.$tamir.'
'; 164 | }else{ 165 | echo ' 166 | '.$first.$tamir.''; 167 | } 168 | 169 | } 170 | 171 | } 172 | 173 | ?> -------------------------------------------------------------------------------- /api/models/email.php: -------------------------------------------------------------------------------- 1 | email = $email; 15 | } 16 | 17 | public function __toString() 18 | { 19 | return $this->email; 20 | } 21 | 22 | public function jsonSerialize(): mixed 23 | { 24 | return $this->email; 25 | } 26 | } 27 | 28 | ?> -------------------------------------------------------------------------------- /api/models/name.php: -------------------------------------------------------------------------------- 1 | Name = $Name; 15 | } 16 | 17 | public function __toString() 18 | { 19 | return $this->Name; 20 | } 21 | 22 | public function jsonSerialize(): mixed 23 | { 24 | return $this->Name; 25 | } 26 | } 27 | 28 | 29 | ?> -------------------------------------------------------------------------------- /api/models/resellerpackage.php: -------------------------------------------------------------------------------- 1 | ResellerPackageID = $ResellerPackageID; 19 | $this->Name = $Name; 20 | $this->MaxBandwidth = $MaxBandwidth; 21 | $this->MaxDiskUsage = $MaxDiskUsage; 22 | $this->MaxUsers = $MaxUsers; 23 | $this->MaxDomains = $MaxDomains; 24 | $this->MaxSubDomains = $MaxSubDomains; 25 | $this->MaxDatabases = $MaxDatabases; 26 | $this->MaxFTPAccounts = $MaxFTPAccounts; 27 | } 28 | 29 | public static function dbResellerPackageToObject(array $dbResellerPackage): self { 30 | return new ResellerPackage( 31 | $dbResellerPackage['ResellerPackageID'], 32 | new Name($dbResellerPackage['Name']), 33 | $dbResellerPackage['MaxBandwidth'], 34 | $dbResellerPackage['MaxDiskUsage'], 35 | $dbResellerPackage['MaxUsers'], 36 | $dbResellerPackage['MaxDomains'], 37 | $dbResellerPackage['MaxSubDomains'], 38 | $dbResellerPackage['MaxDatabases'], 39 | $dbResellerPackage['MaxFTPAccounts'] 40 | ); 41 | } 42 | 43 | public static function selectAll(): ResellerPackages{ 44 | $db = \API\DB::getInstance(); 45 | $dbResellerPackages = $db->getResellerPackages(); 46 | if(!$dbResellerPackages['success'] || count($dbResellerPackages['results']) == 0) { 47 | throw new \Exception('Reseller packages not found'); 48 | } 49 | return new ResellerPackages($dbResellerPackages['results']); 50 | } 51 | 52 | public static function selectByID(int $id): self{ 53 | $db = \API\DB::getInstance(); 54 | $dbResellerPackage = $db->getResellerPackageByID($id); 55 | if(!$dbResellerPackage['success'] || count($dbResellerPackage['results']) == 0) { 56 | throw new \Exception('Reseller package not found'); 57 | } 58 | return self::dbResellerPackageToObject($dbResellerPackage['results'][0]); 59 | } 60 | 61 | public function create(): self { 62 | $db = \API\DB::getInstance(); 63 | $dbResellerPackage = $db->addResellerPackage($this->Name, $this->MaxUsers, $this->MaxBandwidth, $this->MaxDiskUsage, $this->MaxDomains, $this->MaxSubDomains, $this->MaxDatabases, $this->MaxFTPAccounts); 64 | if(!$dbResellerPackage['success']) { 65 | throw new \Exception('Reseller package not created'); 66 | } 67 | $this->ResellerPackageID = $db->lastInsertId(); 68 | return $this; 69 | } 70 | 71 | } 72 | 73 | class ResellerPackages implements Countable, \Iterator { 74 | public array $ResellerPackages; 75 | 76 | public function __construct(array $ResellerPackages) { 77 | $this->ResellerPackages = array(); 78 | $ResellerPackagesObjects = array(); 79 | foreach($ResellerPackages as $ResellerPackage) { 80 | if($ResellerPackage instanceof ResellerPackage) { 81 | array_push($ResellerPackagesObjects, $ResellerPackage); 82 | continue; 83 | }else{ 84 | $ResellerPackageObject = ResellerPackage::dbResellerPackageToObject($ResellerPackage); 85 | array_push($ResellerPackagesObjects, $ResellerPackageObject); 86 | } 87 | } 88 | $this->ResellerPackages = $ResellerPackagesObjects; 89 | } 90 | 91 | public function count(): int { 92 | return count($this->ResellerPackages); 93 | } 94 | 95 | public function current(): ResellerPackage { 96 | return current($this->ResellerPackages); 97 | } 98 | 99 | public function key(): int { 100 | return key($this->ResellerPackages); 101 | } 102 | 103 | public function next(): void { 104 | next($this->ResellerPackages); 105 | } 106 | 107 | public function rewind(): void { 108 | reset($this->ResellerPackages); 109 | } 110 | 111 | public function valid(): bool { 112 | return key($this->ResellerPackages) !== null; 113 | } 114 | 115 | } 116 | 117 | ?> -------------------------------------------------------------------------------- /api/models/role.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/models/user.php: -------------------------------------------------------------------------------- 1 | UserID = $UserID; 27 | $this->Username = $Username; 28 | $this->Email = $Email; 29 | $this->FName = $FName; 30 | $this->LName = $LName; 31 | $this->Suspended = $Suspended; 32 | $this->Admin = $Admin; 33 | $this->Reseller = $Reseller; 34 | $this->ResellerID = $ResellerID; 35 | $this->ResellerPackageID = $ResellerPackageID; 36 | $this->UserCount = $UserCount; 37 | 38 | $this->UserType = new UserType($Admin, $Reseller); 39 | } 40 | 41 | public static function dbUserToObject(array $dbUser): self { 42 | $user = new self( 43 | $dbUser['UserID'], 44 | new Name($dbUser['Username']), 45 | new Email($dbUser['Email']), 46 | new Name($dbUser['FName']), 47 | new Name($dbUser['LName']), 48 | boolval($dbUser['Suspended']), 49 | boolval($dbUser['Admin']), 50 | boolval($dbUser['Reseller']), 51 | $dbUser['ResellerID'], 52 | $dbUser['ResellerPackageID'], 53 | $dbUser['UserCount'] 54 | ); 55 | 56 | if($user->ResellerID != null) { 57 | $user->ResellerUser = self::selectByID($dbUser['ResellerID']); 58 | } 59 | 60 | if($user->ResellerPackageID != null) { 61 | $user->ResellerPackage = ResellerPackage::selectByID($dbUser['ResellerPackageID']); 62 | } 63 | 64 | return $user; 65 | } 66 | 67 | public static function selectAll(): Users { 68 | $db = \API\DB::getInstance(); 69 | $users = $db->getAllUsers(); 70 | if(!$users['success'] || count($users['results']) == 0) { 71 | throw new \Exception('Users not found'); 72 | } 73 | return new Users($users['results']); 74 | } 75 | 76 | public static function selectByID(int $id): self { 77 | $db = \API\DB::getInstance(); 78 | $user = $db->getUserByID($id); 79 | if(!$user['success'] || count($user['results']) == 0) throw new \Exception("User not found"); 80 | 81 | return self::dbUserToObject($user['results'][0]); 82 | } 83 | 84 | public static function selectByEmail(Email $email): self { 85 | $db = \API\DB::getInstance(); 86 | $user = $db->getEmailDetails($email); 87 | if(!$user['success'] || count($user['results']) == 0) throw new \Exception("User not found"); 88 | 89 | return self::dbUserToObject($user['results'][0]); 90 | } 91 | 92 | public static function selectByUsername(Name $username): self { 93 | $db = \API\DB::getInstance(); 94 | $user = $db->getUserDetails($username); 95 | if(!$user['success'] || count($user['results']) == 0) throw new \Exception("User not found"); 96 | 97 | return self::dbUserToObject($user['results'][0]); 98 | } 99 | 100 | public function create(string $pass): self { 101 | $db = \API\DB::getInstance(); 102 | 103 | $salt = \API\Auth\Session::generateSalt(); 104 | $hash = \API\Auth\Session::hashPass($pass, $salt); 105 | 106 | $user = $db->addUser((string) $this->Username, $hash, $salt, (string) $this->Email, (string) $this->FName, (string) $this->LName, (int) $this->Admin, (int) $this->Reseller, (int) $this->ResellerID, (int) $this->ResellerPackageID); 107 | if(!$user['success']) throw new \Exception("User not created"); 108 | 109 | $this->UserID = $db->lastInsertId(); 110 | return $this; 111 | } 112 | 113 | public function edit(Name $user, string $pass, Email $email, Name $fname, Name $lname, UserType $userType, ?int $resellerPackageID): self { 114 | $db = \API\DB::getInstance(); 115 | 116 | if($resellerPackageID == null) { 117 | $resellerPackageID = $this->ResellerPackageID; 118 | }else{ 119 | $resellerPackage = ResellerPackage::selectByID($resellerPackageID); 120 | $resellerPackageID = $resellerPackage->ResellerPackageID; 121 | } 122 | 123 | $emailExists = false; 124 | try{ 125 | $emailUser = User::selectByEmail($email); 126 | if($emailUser->UserID !== $this->UserID) $emailExists = true; 127 | }catch(\Exception $e){ 128 | // Do nothing 129 | }finally{ 130 | if($emailExists){ 131 | throw new \Exception('Email already exists'); 132 | } 133 | } 134 | 135 | $usernameExists = false; 136 | 137 | try{ 138 | $usernameUser = User::selectByUsername($user); 139 | if($usernameUser->UserID !== $this->UserID) $usernameExists = true; 140 | }catch(\Exception $e){ 141 | // Do nothing 142 | }finally{ 143 | if($usernameExists){ 144 | throw new \Exception('Username already exists'); 145 | } 146 | } 147 | 148 | try{ 149 | if($userType->isReseller()){ 150 | if($this->ResellerPackageID) ResellerPackage::selectByID($user->ResellerPackageID); 151 | else throw new \Exception('Reseller package not selected'); 152 | }elseif($userType->isUser()){ 153 | // TODO: Check for UserPackageID 154 | if($this->ResellerID) User::selectByID($user->ResellerID); 155 | else throw new \Exception('Reseller not selected'); 156 | } 157 | }catch(\Exception $e){ 158 | throw $e; 159 | } 160 | 161 | $userQuery = $db->editUser($this->UserID, (string) $user, (string) $email, (string) $fname, (string) $lname, (int) $userType->isAdmin(), (int) $userType->isReseller(), $resellerPackageID); 162 | if(!empty($pass)){ 163 | $salt = \API\Auth\Session::generateSalt(); 164 | $pass = \API\Auth\Session::hashPass($pass, $salt); 165 | $db->editUserPassword($this->UserID, $pass, $salt); 166 | 167 | } 168 | if(!$userQuery['success']) throw new \Exception("User not edited"); 169 | 170 | return $this; 171 | } 172 | 173 | public function delete(): bool { 174 | $db = \API\DB::getInstance(); 175 | $db->deleteUserByID($this->UserID); 176 | return true; 177 | } 178 | 179 | public static function isAdmin(User $user): bool { 180 | return $user->Admin; 181 | } 182 | 183 | public static function isReseller(User $user): bool { 184 | return $user->Reseller; 185 | } 186 | 187 | public static function isUser(User $user): bool { 188 | return !$user->Admin && !$user->Reseller; 189 | } 190 | 191 | public function fullName(): string { 192 | return $this->FName . ' ' . $this->LName; 193 | } 194 | } 195 | 196 | class Users implements Countable, \Iterator { 197 | public array $users; 198 | 199 | public function __construct(array $users) { 200 | $this->users = array(); 201 | $userObjects = array(); 202 | foreach($users as $user) { 203 | if($user instanceof User) { 204 | array_push($userObjects, $user); 205 | continue; 206 | }else{ 207 | $userObject = User::dbUserToObject($user); 208 | array_push($userObjects, $userObject); 209 | } 210 | } 211 | $this->users = $userObjects; 212 | } 213 | 214 | public function count(): int { 215 | return count($this->users); 216 | } 217 | 218 | public function current(): User { 219 | return current($this->users); 220 | } 221 | 222 | public function key(): int { 223 | return key($this->users); 224 | } 225 | 226 | public function next(): void { 227 | next($this->users); 228 | } 229 | 230 | public function rewind(): void { 231 | reset($this->users); 232 | } 233 | 234 | public function valid(): bool { 235 | return key($this->users) !== null; 236 | } 237 | 238 | public function filter(string $filter): Users { 239 | $filteredUsers = array_filter($this->users, "API\Models\User::$filter"); 240 | return new Users($filteredUsers); 241 | } 242 | 243 | public function filterByType(UserType $type): Users{ 244 | $filteredUsers = array_filter($this->users, function(User $user) use ($type){ 245 | return $user->UserType == $type; 246 | }); 247 | return new Users($filteredUsers); 248 | } 249 | 250 | } 251 | 252 | ?> -------------------------------------------------------------------------------- /api/models/usertype.php: -------------------------------------------------------------------------------- 1 | type = Role::Admin; 12 | } else if($reseller){ 13 | $this->type = Role::Reseller; 14 | } else { 15 | $this->type = Role::User; 16 | } 17 | } 18 | 19 | public function __toString(): string{ 20 | return match($this->type){ 21 | Role::Admin => 'Admin', 22 | Role::Reseller => 'Reseller', 23 | Role::User => 'User', 24 | }; 25 | } 26 | 27 | public function jsonSerialize(): mixed 28 | { 29 | return $this->__toString(); 30 | } 31 | 32 | public static function Admin(): UserType{ 33 | return new UserType(true, false); 34 | } 35 | 36 | public static function Reseller(): UserType{ 37 | return new UserType(false, true); 38 | } 39 | 40 | public static function User(): UserType{ 41 | return new UserType(false, false); 42 | } 43 | 44 | public function getRole(): Role{ 45 | return $this->type; 46 | } 47 | 48 | public function isAdmin(): bool{ 49 | return $this->type == Role::Admin; 50 | } 51 | 52 | public function isReseller(): bool{ 53 | return $this->type == Role::Reseller; 54 | } 55 | 56 | public function isUser(): bool{ 57 | return $this->type == Role::User; 58 | } 59 | 60 | public function isNotUser(): bool{ 61 | return $this->type == Role::Admin || $this->type == Role::Reseller; 62 | } 63 | } -------------------------------------------------------------------------------- /assets/css/panel.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Encode Sans"; 3 | src: url("/assets/fonts/encode-sans.condensed.ttf"); 4 | } 5 | 6 | html, 7 | body { 8 | height: 100%; 9 | } 10 | 11 | body { 12 | display: flex; 13 | background-color: #f5f5f5; 14 | align-items: unset; 15 | } 16 | 17 | #main { 18 | display: block; 19 | width: 100%; 20 | padding: 0; 21 | } 22 | 23 | #main>* { 24 | opacity: 1; 25 | transition: 1s; 26 | } 27 | 28 | #main.fadeout * { 29 | opacity: 0; 30 | } 31 | 32 | #toasts { 33 | position: fixed; 34 | bottom: 1vh; 35 | right: 1vw; 36 | min-width: 20vw; 37 | z-index: 1060; 38 | } 39 | 40 | #body-row { 41 | margin-left: 0; 42 | margin-right: 0; 43 | } 44 | 45 | #sidebar-container { 46 | min-height: 100vh; 47 | background-color: #333; 48 | padding: 0; 49 | } 50 | 51 | .navbar-toggler { 52 | border-color: rgba(255, 255, 255, 0) !important; 53 | outline: unset !important; 54 | } 55 | 56 | .navbar-toggler i { 57 | color: white; 58 | transition: 0.2s !important; 59 | } 60 | 61 | .navbar-toggler i:hover { 62 | background-color: #045F8C; 63 | border-radius: 65px; 64 | padding: 12px; 65 | margin: -12px; 66 | outline: unset !important; 67 | } 68 | 69 | 70 | /* Sidebar sizes when expanded and expanded */ 71 | 72 | .sidebar-expanded { 73 | width: 230px; 74 | } 75 | 76 | .sidebar-collapsed { 77 | width: 60px; 78 | } 79 | 80 | 81 | /* Menu item*/ 82 | 83 | #sidebar-container .list-group a { 84 | height: 50px; 85 | color: white; 86 | } 87 | 88 | 89 | /* Submenu item*/ 90 | 91 | #sidebar-container .list-group .sidebar-submenu a { 92 | height: 45px; 93 | padding-left: 30px; 94 | } 95 | 96 | .sidebar-submenu { 97 | font-size: 0.9rem; 98 | } 99 | 100 | 101 | /* Separators */ 102 | 103 | .sidebar-separator-title { 104 | background-color: #333; 105 | height: 35px; 106 | } 107 | 108 | .sidebar-separator { 109 | background-color: #333; 110 | height: 25px; 111 | } 112 | 113 | .logo-separator { 114 | background-color: #333; 115 | } 116 | 117 | 118 | /* Closed submenu icon */ 119 | 120 | 121 | /*a[href='#account'] .submenu-icon::after { 122 | content: " \f0da"; 123 | font-family: FontAwesome; 124 | display: inline; 125 | text-align: right; 126 | padding-left: 10px; 127 | }*/ 128 | 129 | .menu-collapsed { 130 | transition: unset !important; 131 | } 132 | 133 | 134 | /* Opened submenu icon */ 135 | 136 | #sidebar-container .list-group .list-group-item[aria-expanded="true"] .submenu-icon::after { 137 | content: " \f0da"; 138 | font-family: FontAwesome; 139 | display: inline; 140 | text-align: right; 141 | padding-left: 10px; 142 | } 143 | 144 | .clickable { 145 | cursor: pointer; 146 | } 147 | 148 | .iconRotate { 149 | -moz-transform: rotate(0deg); 150 | -webkit-transform: rotate(0deg); 151 | -o-transform: rotate(0deg); 152 | -ms-transform: rotate(0deg); 153 | transform: rotate(0deg); 154 | } 155 | 156 | .iconRotated { 157 | -moz-transform: rotate(90deg); 158 | -webkit-transform: rotate(90deg); 159 | -o-transform: rotate(90deg); 160 | -ms-transform: rotate(90deg); 161 | transform: rotate(90deg); 162 | } 163 | 164 | .sidebarc { 165 | transition: 1s !important; 166 | position: fixed; 167 | top: 56px; 168 | bottom: 0; 169 | overflow-y: overlay !important; 170 | overflow-y: auto; 171 | padding-bottom: 56px !important; 172 | } 173 | 174 | .mcontent { 175 | margin-left: 230px; 176 | transition: 1s !important; 177 | } 178 | 179 | .card-header { 180 | font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; 181 | font-size: 17px; 182 | } 183 | 184 | .card-text { 185 | /*font-family: 'Lato', sans-serif !important;*/ 186 | font-family: "Encode Sans" !important; 187 | /*font-weight: 600;*/ 188 | } 189 | 190 | .card.disabled { 191 | background: #d2d2d2; 192 | color: #6c757d!important; 193 | } 194 | 195 | .tooltipRed + .tooltip > .tooltip-inner { 196 | color: #f55; 197 | } 198 | 199 | /* .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-retroorange, 200 | .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-retroorange { 201 | color: #fff; 202 | background: #ff9933; 203 | } */ 204 | 205 | /* CUSTOM SWITCH ORANGE */ 206 | 207 | .custom-control-input:checked~.custom-control-label.orange::before { 208 | border-color: #ffbc00; 209 | background-color: #ffbc00; 210 | } 211 | 212 | .custom-control-input:focus~.custom-control-label.orange::before { 213 | box-shadow: 0 0 0 0.2rem rgba(255,188,0,.25); 214 | } 215 | 216 | .custom-control-input:focus:not(:checked)~.custom-control-label.orange::before { 217 | border-color: #ffbc00; 218 | } 219 | 220 | /* CUSTOM SWITCH RED */ 221 | 222 | .custom-control-input:checked~.custom-control-label.red::before { 223 | border-color: #ff4040; 224 | background-color: #ff4040; 225 | } 226 | 227 | .custom-control-input:focus~.custom-control-label.red::before { 228 | box-shadow: 0 0 0 0.2rem rgba(255,64,64,.25); 229 | } 230 | 231 | .custom-control-input:focus:not(:checked)~.custom-control-label.red::before { 232 | border-color: #ff4040; 233 | } 234 | 235 | .custom-control-label.center::before, .custom-control-label.center::after{ 236 | margin-top: 5px !important; 237 | } -------------------------------------------------------------------------------- /assets/css/signin.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | width: 100%; 5 | } 6 | 7 | body { 8 | display: -ms-flexbox; 9 | display: flex; 10 | -ms-flex-align: center; 11 | align-items: center; 12 | background-color: #f5f5f5; 13 | } 14 | 15 | #main { 16 | display: contents; 17 | padding-top: 40px; 18 | padding-bottom: 40px; 19 | width: 100%; 20 | } 21 | 22 | #main * { 23 | opacity: 1; 24 | transition: 1s opacity; 25 | } 26 | 27 | #main.fadeout * { 28 | opacity: 0; 29 | /*transition: none;*/ 30 | } 31 | 32 | .form-signin { 33 | width: 100%; 34 | max-width: 330px; 35 | padding: 15px; 36 | margin: auto; 37 | } 38 | 39 | .form-signin h1 { 40 | text-shadow: 0px 0px 10px #7a88f580; 41 | } 42 | 43 | .form-signin .checkbox { 44 | font-weight: 400; 45 | } 46 | 47 | .form-signin .form-control { 48 | position: relative; 49 | box-sizing: border-box; 50 | height: auto; 51 | padding: 10px; 52 | font-size: 16px; 53 | } 54 | 55 | .form-signin .form-control:focus { 56 | z-index: 2; 57 | } 58 | 59 | .form-signin input[type="text"] { 60 | margin-bottom: -1px; 61 | border-bottom-right-radius: 0; 62 | border-bottom-left-radius: 0; 63 | } 64 | 65 | .form-signin input[type="password"] { 66 | margin-bottom: 10px; 67 | border-top-left-radius: 0; 68 | border-top-right-radius: 0; 69 | } 70 | 71 | #toasts { 72 | position: absolute; 73 | bottom: 1vh; 74 | right: 1vw; 75 | min-width: 20vw; 76 | z-index: 10; 77 | } -------------------------------------------------------------------------------- /assets/fonts/adlanta.light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/fonts/adlanta.light.otf -------------------------------------------------------------------------------- /assets/fonts/encode-sans.condensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/fonts/encode-sans.condensed.ttf -------------------------------------------------------------------------------- /assets/images/Banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/images/Banner.gif -------------------------------------------------------------------------------- /assets/images/icon-lg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/images/icon-lg.gif -------------------------------------------------------------------------------- /assets/images/icon-md.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/images/icon-md.gif -------------------------------------------------------------------------------- /assets/images/icon-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/images/icon-sm.gif -------------------------------------------------------------------------------- /assets/images/icon-xs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamirSlo/TSHostingPanel/957173fb62cd470cda4a9931878f3ba3da594b49/assets/images/icon-xs.gif -------------------------------------------------------------------------------- /assets/js/popper.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) Federico Zivolo 2019 3 | Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). 4 | */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?pe:10===e?se:pe||se}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),le({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=fe({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u);(m||b||y)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),y&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=fe({},e.offsets.popper,D(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=C(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!me),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=H('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=fe({},E,e.attributes),e.styles=fe({},m,e.styles),e.arrowStyles=fe({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return j(e.instance.popper,e.styles),V(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&j(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),j(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ue}); 5 | //# sourceMappingURL=popper.min.js.map 6 | -------------------------------------------------------------------------------- /assets/js/toasts.js: -------------------------------------------------------------------------------- 1 | var eToastNum = 0 2 | var sToastNum = 0 3 | var cToastNum = 0 4 | 5 | function generateErrorToast() { 6 | eToastNum = eToastNum + 1; 7 | $("#toasts").append(''); 18 | return eToastNum; 19 | } 20 | 21 | function generateSuccessToast() { 22 | sToastNum = sToastNum + 1; 23 | $("#toasts").append(''); 35 | return sToastNum; 36 | } 37 | 38 | function generateConfirmToast(onConfirm) { 39 | cToastNum = cToastNum + 1; 40 | $("#toasts").append(''); 52 | return cToastNum; 53 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | 7 | $tshp = TSHP::getInstance(); 8 | ?> 9 | 10 | 11 | 12 | 13 | Web Hosting Panel 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 38 |
39 | 40 |
41 |
42 | 43 |
44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /reseller/account/messages/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Messages

14 | 15 | footer(); 17 | ?> 18 | 19 |
-------------------------------------------------------------------------------- /reseller/account/password/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Passwords

14 | 15 | footer(); 17 | ?> 18 | 19 |
-------------------------------------------------------------------------------- /reseller/account/settings/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Account Settings

14 | 15 | footer(); 17 | ?> 18 | 19 |
-------------------------------------------------------------------------------- /reseller/help/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Help

14 | 15 | footer(); 17 | ?> 18 | 19 |
-------------------------------------------------------------------------------- /reseller/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 |

Dashboard

13 | 14 | 15 |
16 |

Reseller Quota

17 |
18 |
19 |
20 | Users 21 |
22 |
2 (3)
23 |
24 |
25 |
26 | Domains 27 |
28 |
2 (10)
29 |
30 |
31 |
32 | Disk Space 33 |
34 |
1 (∞)
35 |
36 |
37 |
38 |
39 |
40 | 41 | footer(); 43 | ?> 44 | -------------------------------------------------------------------------------- /reseller/menu.php: -------------------------------------------------------------------------------- 1 | user->FName; 6 | $lname = $tshp->user->LName; 7 | $admin = $tshp->user->Admin; 8 | 9 | 10 | ?> 11 | 12 | -------------------------------------------------------------------------------- /reseller/packages/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | 12 | ?> 13 | 14 |

Reseller Packages

15 |
16 |
17 |

Packages List

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | There are no Reseller Packages within this Web Hosting Panel yet... Add a package here 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
Package NameBandwidthDisk UsageUsersDomainsDatabasesActions
41 | 42 |
43 |
44 | 45 | 46 | 47 | 48 | 49 | 124 | 125 | footer(); 127 | ?> 128 | -------------------------------------------------------------------------------- /reseller/sidebar.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /reseller/system/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | 12 | ?> 13 | 14 |

System Information

15 |
16 |
17 |

General

18 |
19 | 20 |
21 |

22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
UptimeCPUs Count
05:00:282
36 |
37 |
38 | 39 |
40 |
41 |

CPUs Information

42 |
43 | 44 |
45 |

46 | 47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
Processor NameVendor IDProcessor Speed (MHz)
Example 2Try4
62 |
63 |
64 | 65 |
66 |
67 |

Memory Information

68 |
69 | 70 |
71 |

72 | 73 |
74 |
75 |
76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
Total MemoryFree MemoryAvailable MemoryTotal Swap MemoryFree Swap MemoryCached Swap Memory
640 KB12KB0 B0 B0 B0 B
94 |
95 |
96 | 97 |
98 |
99 |

Load Average

100 |
101 | 102 |
103 |

104 | 105 |
106 |
107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
1 minute10 minutes25 minutes
0.90.40.25
120 |
121 |
122 | 123 | footer(); 125 | ?> 126 | -------------------------------------------------------------------------------- /reseller/system/logs/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | 12 | ?> 13 | 14 |

Logs

15 |
16 | Please select a log file to view: 17 | 27 |
28 | 29 |
30 | Options: 31 | 32 |
33 | 34 | footer(); 36 | ?> 37 | -------------------------------------------------------------------------------- /reseller/system/settings/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | 12 | ?> 13 | 14 |

Reseller Settings

15 | 16 | footer(); 18 | ?> 19 | -------------------------------------------------------------------------------- /reseller/users/backups/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Backups

14 | 15 | footer(); 17 | ?> -------------------------------------------------------------------------------- /reseller/users/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

Domains

14 |
15 |
16 |

Active domains

17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
IDDomainSSLFTP accountsDatabasesActions
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 50 | 51 | 52 |
1demo.com1/101/∞ 41 | 47 | 48 | 49 |
53 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 82 | 83 | 84 |
2mysite.com1/100/∞ 79 | 80 | 81 |
85 |
86 |
87 | 88 | footer(); 90 | ?> 91 | -------------------------------------------------------------------------------- /reseller/users/messages/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->headerReseller(); 11 | ?> 12 | 13 |

User Messages

14 | 15 | footer(); 17 | ?> -------------------------------------------------------------------------------- /user/domains/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->header(); 11 | ?> 12 | 13 |

Domains

14 |
15 |
16 |

Active domains

17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
IDDomainSSLFTP accountsDatabasesActions
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 50 | 51 | 52 |
1demo.com1/101/∞ 41 | 47 | 48 | 49 |
53 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 82 | 83 | 84 |
2mysite.com1/100/∞ 79 | 80 | 81 |
85 |
86 |
87 | 88 | footer(); 90 | ?> 91 | -------------------------------------------------------------------------------- /user/index-slim.php: -------------------------------------------------------------------------------- 1 | 34 | 35 | 65 | 66 | 67 | 68 |
69 | 70 | 153 | 154 | 155 |
156 | 157 |

158 | Collapsing Menu 159 | Version 2.1 160 |

161 | 162 | 163 |
164 |

Requirements

165 |
166 |
    167 |
  • JQuery
  • 168 |
  • Bootstrap 4 beta-3
  • 169 |
170 |
171 |
172 | 173 | 174 | 175 |
176 | 177 |
178 |
-------------------------------------------------------------------------------- /user/index.php: -------------------------------------------------------------------------------- 1 | Couldn't require Main Class."); 5 | 6 | $tshp = TSHP::getInstance(); 7 | 8 | $ui = new UI(); 9 | 10 | $ui->header(); 11 | ?> 12 |

Dashboard

13 | 14 | 15 |
16 |

User Quota

17 |
18 |
19 |
20 | Domains 21 |
22 |
2 (3)
23 |
24 |
25 |
26 | FTP Accounts 27 |
28 |
2 (10)
29 |
30 |
31 |
32 | Databases 33 |
34 |
1 (∞)
35 |
36 |
37 |
38 |
39 |
40 | 41 | footer(); 43 | ?> 44 | -------------------------------------------------------------------------------- /user/menu.php: -------------------------------------------------------------------------------- 1 | user->FName; 6 | $lname = $tshp->user->LName; 7 | $admin = $tshp->user->Admin; 8 | $reseller = $tshp->user->Reseller; 9 | 10 | ?> 11 | 12 | -------------------------------------------------------------------------------- /user/sidebar.php: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------