@@ -25,57 +25,128 @@ 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+ }
5576
77+ private function __validate_disabled () {
78+ # Check for our optional `disabled` payload value
5679 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
80+ $ this ->validated_data ["disabled " ] = "" ;
6081 }
82+ }
6183
84+ private function __validate_descr () {
85+ # Check for our optional `descr` payload value
6286 if (isset ($ this ->initial_data ['descr ' ])) {
63- $ this ->validated_data ["descr " ] = trim ( $ this ->initial_data ['descr ' ]); // Update our user's full name
87+ $ this ->validated_data ["descr " ] = $ this ->initial_data ['descr ' ];
6488 }
89+ }
6590
91+ private function __validate_expires () {
92+ # Check for our optional `expires` payload value
6693 if (isset ($ this ->initial_data ['expires ' ])) {
67- $ this ->validated_data ["expires " ] = trim ($ this ->initial_data ['expires ' ]); // Update our user's expiration date
94+ # Try to format the date string, return an error if the format is invalid
95+ try {
96+ $ this ->validated_data ["expires " ] = (new DateTime ($ this ->initial_data ['expires ' ]))->format ("m/d/Y " );
97+ } catch (Exception $ e ) {
98+ $ this ->errors [] = APIResponse \get (5040 );
99+ }
68100 }
101+ }
69102
103+ private function __validate_authorizedkeys () {
104+ # Check for our optional `authorizedkeys` payload value
70105 if (isset ($ this ->initial_data ['authorizedkeys ' ])) {
71- $ this ->validated_data ["authorizedkeys " ] = trim ( $ this ->initial_data ['authorizedkeys ' ]); // Update our user's authorized keys
106+ $ this ->validated_data ["authorizedkeys " ] = $ this ->initial_data ['authorizedkeys ' ];
72107 }
108+ }
73109
110+ private function __validate_ipsecpsk () {
111+ # Check for our optional `ipsecpsk` payload value
74112 if (isset ($ this ->initial_data ['ipsecpsk ' ])) {
75- $ this ->validated_data ["ipsecpsk " ] = trim ($ this ->initial_data ['ipsecpsk ' ]); // Update our user's IPsec pre-shared key
113+ # Ensure the PSK does not contain invalid characters
114+ if (preg_match ('/^[[:ascii:]]*$/ ' , $ _POST ['ipsecpsk ' ])) {
115+ $ this ->validated_data ["ipsecpsk " ] = $ this ->initial_data ['ipsecpsk ' ];
116+ } else {
117+ $ this ->errors [] = APIResponse \get (5039 );
118+ }
76119 }
120+ }
121+
122+ public function validate_payload () {
123+ # Set static object values
124+ $ this ->validated_data ["uid " ] = $ this ->config ["system " ]["nextuid " ];
125+ $ this ->validated_data ["scope " ] = "user " ;
126+ $ this ->validated_data ["priv " ] = [];
77127
78- $ this ->validated_data ["scope " ] = "user " ; // Set our new user's system scope
79- $ this ->validated_data ["priv " ] = []; // Default our privs to empty array
128+ # Run each validation method
129+ $ this ->__validate_username ();
130+ $ this ->__validate_password ();
131+ $ this ->__validate_descr ();
132+ $ this ->__validate_disabled ();
133+ $ this ->__validate_expires ();
134+ $ this ->__validate_authorizedkeys ();
135+ $ this ->__validate_ipsecpsk ();
80136 }
137+
138+ public function is_username_reserved ($ user ) {
139+ # Open the /etc/passwd file to read all system users
140+ $ etc_passwd = explode (PHP_EOL , file_get_contents ("/etc/passwd " ));
141+
142+ # Loop through each system user and check if the username is reserved
143+ foreach ($ etc_passwd as $ sys_user_ent ) {
144+ $ sys_username = explode (": " , $ sys_user_ent )[0 ];
145+ if ($ sys_username == $ user ) {
146+ return true ;
147+ }
148+ }
149+ return false ;
150+ }
151+
81152}
0 commit comments