@@ -25,57 +25,151 @@ class APIUserCreate extends APIModel {
2525 }
2626
2727 public function action () {
28+ # Increase the system's next UID by one and add our user to the configuration
29+ $ this ->config ["system " ]["nextuid " ] = strval (intval ($ this ->validated_data ["uid " ]) + 1 );
2830 $ this ->config ['system ' ]['user ' ][] = $ this ->validated_data ;
29- $ this ->config ["system " ]["nextuid " ] = strval (intval ($ this ->validated_data ["uid " ]) + 1 ); // Increase our next UID
30- local_user_set_password ($ this ->validated_data , $ this ->validated_data ["password " ]); // Set our new user's password
31- local_user_set ($ this ->validated_data );
31+
32+ # Write the user to configuration and set the user on the backend. Return response with created user object.
3233 $ this ->write_config ();
33- $ userindex = index_users (); // Update our user index
34+ local_user_set ( $ this -> validated_data );
3435 return APIResponse \get (0 , $ this ->validated_data );
3536 }
3637
37- public function validate_payload () {
38- $ this -> validated_data [ " uid " ] = $ this -> config [ " system " ][ " nextuid " ]; // Save our next UID
38+ private function __validate_username () {
39+ # Check for our required `username` payload value
3940 if (isset ($ this ->initial_data ['username ' ])) {
40- // Check that our user already exists
41- if (array_key_exists ($ this ->initial_data ['username ' ], index_users ())) {
42- $ this ->errors [] = APIResponse \get (5002 );
41+ # Ensure a user with this username does not already exist
42+ if (!array_key_exists ($ this ->initial_data ['username ' ], index_users ())) {
43+ # Ensure the username does not contain invalid characters
44+ if (!preg_match ("/[^a-zA-Z0-9\.\-_]/ " , $ this ->initial_data ['username ' ])) {
45+ # Ensure username is not reserved by the system
46+ if (!$ this ->is_username_reserved ($ this ->initial_data ["username " ])) {
47+ # Ensure username is not longer that 32 characters
48+ if (strlen ($ this ->initial_data ["username " ]) <= 32 ) {
49+ $ this ->validated_data ["name " ] = $ this ->initial_data ['username ' ];
50+ } else {
51+ $ this ->errors [] = APIResponse \get (5038 );
52+ }
53+ } else {
54+ $ this ->errors [] = APIResponse \get (5037 );
55+ }
56+ } else {
57+ $ this ->errors [] = APIResponse \get (5036 );
58+ }
4359 } else {
44- $ this ->validated_data [ " name " ] = trim ( $ this -> initial_data [ ' username ' ] );
60+ $ this ->errors [ ] = APIResponse \get ( 5002 );
4561 }
4662 } else {
4763 $ this ->errors [] = APIResponse \get (5000 );
4864 }
65+ }
4966
67+ private function __validate_password () {
68+ # Check for our required `password` payload value
5069 if (isset ($ this ->initial_data ['password ' ])) {
51- $ this ->validated_data ["password " ] = trim ($ this ->initial_data ['password ' ]);
70+ # Generate the password hash and add it to our validated data
71+ local_user_set_password ($ this ->validated_data , $ this ->initial_data ['password ' ]);
5272 } else {
5373 $ this ->errors [] = APIResponse \get (5003 );
5474 }
75+ }
76+
77+ private function __validate_priv () {
78+ global $ priv_list ;
79+ $ this ->validated_data ["priv " ] = [];
80+
81+ # Check for our optional `priv` payload value
82+ if ($ this ->initial_data ["priv " ]) {
83+ # Ensure value is an array
84+ if (!is_array ($ this ->initial_data ["priv " ])) {
85+ $ this ->initial_data ["priv " ] = array ($ this ->initial_data ["priv " ]);
86+ }
87+
88+ # Loop through each requested privilege and ensure it exists
89+ foreach ($ this ->initial_data ["priv " ] as $ priv ) {
90+ if (array_key_exists ($ priv , $ priv_list )) {
91+ $ this ->validated_data ["priv " ][] = $ priv ;
92+ $ this ->validated_data ["priv " ] = array_unique ($ this ->validated_data ["priv " ]);
93+ } else {
94+ $ this ->errors [] = APIResponse \get (5006 );
95+ break ;
96+ }
97+ }
98+ }
99+ }
55100
101+ private function __validate_disabled () {
102+ # Check for our optional `disabled` payload value
56103 if ($ this ->initial_data ["disabled " ] === true ) {
57- $ this ->validated_data ["disabled " ] = "" ; // Update our user's disabled value if not false
58- } elseif ($ this ->initial_data ["disabled " ] === false ) {
59- unset($ this ->validated_data ["disabled " ]); // Unset our disabled value if not requested
104+ $ this ->validated_data ["disabled " ] = "" ;
60105 }
106+ }
61107
108+ private function __validate_descr () {
109+ # Check for our optional `descr` payload value
62110 if (isset ($ this ->initial_data ['descr ' ])) {
63- $ this ->validated_data ["descr " ] = trim ( $ this ->initial_data ['descr ' ]); // Update our user's full name
111+ $ this ->validated_data ["descr " ] = $ this ->initial_data ['descr ' ];
64112 }
113+ }
65114
115+ private function __validate_expires () {
116+ # Check for our optional `expires` payload value
66117 if (isset ($ this ->initial_data ['expires ' ])) {
67- $ this ->validated_data ["expires " ] = trim ($ this ->initial_data ['expires ' ]); // Update our user's expiration date
118+ # Try to format the date string, return an error if the format is invalid
119+ try {
120+ $ this ->validated_data ["expires " ] = (new DateTime ($ this ->initial_data ['expires ' ]))->format ("m/d/Y " );
121+ } catch (Exception $ e ) {
122+ $ this ->errors [] = APIResponse \get (5040 );
123+ }
68124 }
125+ }
69126
127+ private function __validate_authorizedkeys () {
128+ # Check for our optional `authorizedkeys` payload value
70129 if (isset ($ this ->initial_data ['authorizedkeys ' ])) {
71- $ this ->validated_data ["authorizedkeys " ] = trim ($ this ->initial_data ['authorizedkeys ' ]); // Update our user's authorized keys
130+ $ this ->validated_data ["authorizedkeys " ] = base64_encode ($ this ->initial_data ['authorizedkeys ' ]);
72131 }
132+ }
73133
134+ private function __validate_ipsecpsk () {
135+ # Check for our optional `ipsecpsk` payload value
74136 if (isset ($ this ->initial_data ['ipsecpsk ' ])) {
75- $ this ->validated_data ["ipsecpsk " ] = trim ($ this ->initial_data ['ipsecpsk ' ]); // Update our user's IPsec pre-shared key
137+ # Ensure the PSK does not contain invalid characters
138+ if (preg_match ('/^[[:ascii:]]*$/ ' , $ _POST ['ipsecpsk ' ])) {
139+ $ this ->validated_data ["ipsecpsk " ] = $ this ->initial_data ['ipsecpsk ' ];
140+ } else {
141+ $ this ->errors [] = APIResponse \get (5039 );
142+ }
76143 }
144+ }
77145
78- $ this ->validated_data ["scope " ] = "user " ; // Set our new user's system scope
79- $ this ->validated_data ["priv " ] = []; // Default our privs to empty array
146+ public function validate_payload () {
147+ # Set static object values
148+ $ this ->validated_data ["uid " ] = $ this ->config ["system " ]["nextuid " ];
149+ $ this ->validated_data ["scope " ] = "user " ;
150+
151+ # Run each validation method
152+ $ this ->__validate_username ();
153+ $ this ->__validate_password ();
154+ $ this ->__validate_priv ();
155+ $ this ->__validate_descr ();
156+ $ this ->__validate_disabled ();
157+ $ this ->__validate_expires ();
158+ $ this ->__validate_authorizedkeys ();
159+ $ this ->__validate_ipsecpsk ();
160+ }
161+
162+ public function is_username_reserved ($ user ) {
163+ # Open the /etc/passwd file to read all system users
164+ $ sys_users = explode (PHP_EOL , file_get_contents ("/etc/passwd " ));
165+
166+ # Loop through each system user and check if the username is reserved
167+ foreach ($ sys_users as $ sys_user_ent ) {
168+ $ sys_username = explode (": " , $ sys_user_ent )[0 ];
169+ if ($ sys_username == $ user ) {
170+ return true ;
171+ }
172+ }
173+ return false ;
80174 }
81175}
0 commit comments