Procházet zdrojové kódy

refactor(auth): use parameterized expressions for database queries

Replace string interpolation with ExpressionParser.parse_with_params
to safely pass parameters to database queries, eliminating potential
SQL injection vulnerabilities.

Also fix alter_user to properly fetch and update existing entity
instead of creating a new one, and add set_user_enabled method for
toggling user enabled status.
Billy Barrow před 1 měsícem
rodič
revize
bf5038ce17

+ 3 - 2
src/Authentication/UserIdentityProvider.vala

@@ -1,6 +1,7 @@
 using Spry.Authorisation;
 using InvercargillSql.Orm;
 using Invercargill;
+using Invercargill.Expressions;
 using Inversion;
 
 namespace Spry.Authentication {
@@ -11,12 +12,12 @@ namespace Spry.Authentication {
 
         public async Authorisation.Identity? get_identity_by_identifier (Element id) throws Error {
             return yield db.query<UserProjection>()
-                .where(@"id == $(id.as<int64?>())")
+                .where_expr(ExpressionParser.parse_with_params("id == $0", id))
                 .first_async();
         }
         public async Authorisation.Identity? get_identity_by_username (string username) throws Error {
             return yield db.query<UserProjection>()
-                .where(@"username == \"$(username)\"") // XXX FIXME once there is a better way to do this
+                .where_expr(ExpressionParser.parse_with_params("username == $0", new NativeElement<string>(username)))
                 .first_async();
         }
         

+ 26 - 11
src/Authentication/UserService.vala

@@ -1,5 +1,7 @@
 using InvercargillSql.Orm;
 using Spry.Authorisation;
+using Invercargill.Expressions;
+using Invercargill;
 using Inversion;
 
 namespace Spry.Authentication {
@@ -12,7 +14,7 @@ namespace Spry.Authentication {
 
         public async AuthorisationToken? authenticate_user(string username, string password) throws Error {
             var user = yield db.query<UserProjection>()
-                .where(@"username == \"$(username)\"")
+                .where_expr(ExpressionParser.parse_with_params("username == $0", new NativeElement<string>(username)))
                 .first_async();
 
             if(!Sodium.PasswordHashing.check(user.password_hash, password)){
@@ -41,7 +43,7 @@ namespace Spry.Authentication {
 
         public async void set_password(int64 user_id, string password) throws Error {
             var user = yield db.query<UserEntity>()
-                .where(@"id == $user_id")
+                .where_expr(ExpressionParser.parse_with_params("id == $0", new NativeElement<int64?>(user_id)))
                 .first_async();
 
             user.password_hash = Sodium.PasswordHashing.hash(password);
@@ -50,20 +52,33 @@ namespace Spry.Authentication {
         }
 
         public async UserEntity alter_user(int64 user_id, string username, string email, string forename, string surname, DateTime date_of_birth, bool enabled) throws Error {
-            var user = new UserEntity() {
-                username = username,
-                email = email,
-                forename = forename,
-                surname = surname,
-                date_of_birth = date_of_birth,
-                modified = new DateTime.now_utc(),
-                enabled = enabled,
-            };
+            var user = yield db.query<UserEntity>()
+                .where_expr(ExpressionParser.parse_with_params("id == $0", new NativeElement<int64?>(user_id)))
+                .first_async();
+
+            user.username = username;
+            user.email = email;
+            user.forename = forename;
+            user.surname = surname;
+            user.date_of_birth = date_of_birth;
+            user.modified = new DateTime.now_utc();
+            user.enabled = enabled;
 
             db.update<UserEntity>(user);
             return user;
         }
 
+        public async void set_user_enabled(int64 user_id, bool enabled) throws Error {
+            var user = yield db.query<UserEntity>()
+                .where_expr(ExpressionParser.parse_with_params("id == $0", new NativeElement<int64?>(user_id)))
+                .first_async();
+
+            user.modified = new DateTime.now_utc();
+            user.enabled = enabled;
+
+            db.update<UserEntity>(user);
+        }
+
     }
 
 }