forked from GNUsocial/gnu-social
[SECURITY][DB] Make user register 'atomic', by using a single transaction for inserting all objects, to avoid partial inserts
This commit is contained in:
parent
1bad2fa050
commit
b82658e345
@ -93,17 +93,19 @@ class Security extends Controller
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$actor = GSActor::create(['nickname' => $data['nickname']]);
|
$actor = GSActor::create(['nickname' => $data['nickname']]);
|
||||||
DB::persist($actor);
|
$user = LocalUser::create([
|
||||||
DB::flush();
|
|
||||||
$id = $actor->getId();
|
|
||||||
$user = LocalUser::create([
|
|
||||||
'id' => $id,
|
|
||||||
'nickname' => $data['nickname'],
|
'nickname' => $data['nickname'],
|
||||||
'outgoing_email' => $data['email'],
|
'outgoing_email' => $data['email'],
|
||||||
'incoming_email' => $data['email'],
|
'incoming_email' => $data['email'],
|
||||||
'password' => LocalUser::hashPassword($data['password']),
|
'password' => LocalUser::hashPassword($data['password']),
|
||||||
]);
|
]);
|
||||||
DB::persist($user);
|
DB::persistWithSameId(
|
||||||
|
$actor,
|
||||||
|
$user,
|
||||||
|
// Self follow
|
||||||
|
fn (int $id) => DB::persist(Follow::create(['follower' => $id, 'followed' => $id]))
|
||||||
|
);
|
||||||
|
DB::flush();
|
||||||
} catch (UniqueConstraintViolationException $e) {
|
} catch (UniqueConstraintViolationException $e) {
|
||||||
throw new NicknameTakenException;
|
throw new NicknameTakenException;
|
||||||
}
|
}
|
||||||
@ -123,11 +125,6 @@ class Security extends Controller
|
|||||||
$user->setIsEmailVerified(true);
|
$user->setIsEmailVerified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Self follow
|
|
||||||
$follow = Follow::create(['follower' => $id, 'followed' => $id]);
|
|
||||||
DB::persist($follow);
|
|
||||||
DB::flush();
|
|
||||||
|
|
||||||
return $guard_handler->authenticateUserAndHandleSuccess(
|
return $guard_handler->authenticateUserAndHandleSuccess(
|
||||||
$user,
|
$user,
|
||||||
$request,
|
$request,
|
||||||
|
@ -173,6 +173,24 @@ abstract class DB
|
|||||||
return $repo->count($table, $criteria);
|
return $repo->count($table, $criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert all given objects with the generated ID of the first one
|
||||||
|
*/
|
||||||
|
public static function persistWithSameId(object $owner, object | array $others, ?callable $extra = null)
|
||||||
|
{
|
||||||
|
$conn = self::getConnection();
|
||||||
|
$metadata = self::getClassMetadata(get_class($owner));
|
||||||
|
$seqName = $metadata->getSequenceName($conn->getDatabasePlatform());
|
||||||
|
self::persist($owner);
|
||||||
|
$id = $conn->lastInsertId($seqName);
|
||||||
|
F\map(is_array($others) ? $others : [$others], function ($o) use ($id) { $o->setId($id); self::persist($o); });
|
||||||
|
if (!is_null($extra)) {
|
||||||
|
$extra($id);
|
||||||
|
}
|
||||||
|
self::flush();
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intercept static function calls to allow refering to entities
|
* Intercept static function calls to allow refering to entities
|
||||||
* without writing the namespace (which is deduced from the call
|
* without writing the namespace (which is deduced from the call
|
||||||
|
Loading…
Reference in New Issue
Block a user