Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #67

Merged
merged 5 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ Examples: `master`, `develop`, `admin-panel`

## Reporting a Vulnerability

Please mail [email protected] about the security issue.
Please mail `hi [at] semisol [dot] dev` about the security issue.
17 changes: 12 additions & 5 deletions includes/common/db.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace MediaWiki\Extension\ScratchOAuth2\Common;

use Database;
use MediaWiki\MediaWikiServices;

class SOA2DB {
protected static $dbw;
Expand All @@ -24,7 +25,12 @@ public static function dbr() {
}
protected static function dbFactory() {
global $wgSOA2DBtype, $wgSOA2DBserver, $wgSOA2DBuser, $wgSOA2DBpassword, $wgSOA2DBname, $wgSOA2DBprefix;
if (!$wgSOA2DBtype) return wfGetDB;
if (!$wgSOA2DBtype) {
$loadBalancer = MediaWikiServices::getInstance()->getDBLoadBalancer();
return static function ( $index ) use ( $loadBalancer ) {
return $loadBalancer->getConnection( $index );
};
};
$type = $wgSOA2DBtype;
$params = [
'host' => $wgSOA2DBserver,
Expand All @@ -42,24 +48,25 @@ protected static function dbFactory() {
public static function saveUser( int $user_id, string $username ) {
$values = [
'user_id' => $user_id,
'user_name' => strtolower($username)
'user_name' => strtolower($username),
'user_name_cased' => $username
];
self::dbw()->upsert(
'soa2_scratchers', $values,
array_keys($values), $values
'user_id', $values
);
}
public static function getUserById( int $user_id ) {
return self::dbr()->selectRow(
'soa2_scratchers',
['user_id', 'user_name'],
['user_id', 'user_name', 'user_name_cased'],
['user_id' => $user_id]
);
}
public static function getUserByName( string $username ) {
return self::dbr()->selectRow(
'soa2_scratchers',
['user_id', 'user_name'],
['user_id', 'user_name', 'user_name_cased'],
['user_name' => strtolower($username)]
);
}
Expand Down
27 changes: 27 additions & 0 deletions includes/common/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
namespace MediaWiki\Extension\ScratchOAuth2;

use DatabaseUpdater;
use MediaWiki\Extension\ScratchOAuth2\Common\SOA2Login;

require_once __DIR__ . "/consts.php";
require_once __DIR__ . "/login.php";

class SOA2Hooks {
public static function schemaUpdates( DatabaseUpdater $updater ) {
Expand Down Expand Up @@ -39,6 +43,29 @@ public static function schemaUpdates( DatabaseUpdater $updater ) {
'soa2_redirect_uris',
$sql_dir . '/redirect_uris_key.sql'
);
$updater->addExtensionField(
'soa2_scratchers',
'user_name_cased',
$sql_dir . '/cased_usernames.sql'
);
$updater->addExtensionUpdate( [
'MediaWiki\Extension\ScratchOAuth2\SOA2Hooks::fetchCasedUsernames'
] );
return true;
}

public static function fetchCasedUsernames( DatabaseUpdater $updater ) {
// add cased usernames for those who don't have them
$dbw = $updater->getDB();
$res = $dbw->select(
'soa2_scratchers',
['user_id', 'user_name'],
['user_name_cased' => null]
);
foreach ($res as $row) {
$username = $row->user_name;
$updater->output( "Fetching cased username for $username\n" );
SOA2Login::api( $username );
}
}
}
20 changes: 14 additions & 6 deletions includes/common/login.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,26 @@ public static function gen_code( $session ) {
return $session->get( 'soa2_scratch_code' );
}
/**
* Get the data needed to complete a login.
* @param string $username the username to get the codes for
* Get and save user data from the API.
* @param string $username the username to get the data for
*/
public static function codes( string $username ) {
global $wgRequest;
public static function api( string $username ) {
// get user data from API
$user = json_decode(file_get_contents(sprintf(
SOA2_USERS_API, urlencode($username))), true);
if (!$user) return null;
// save user data
$username = $user['username'];
// save it to DB, possibly updating the case
SOA2DB::saveUser( $user['id'], $user['username'] );
return $user;
}
/**
* Get the data needed to complete a login.
* @param string $username the username to get the codes for
*/
public static function codes( string $username ) {
global $wgRequest;
$user = self::api( $username );
$username = $user['username'];
// actually do the code generation
$session = $wgRequest->getSession();
$session->persist();
Expand Down
5 changes: 3 additions & 2 deletions includes/common/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ public static function makeProfileLink($username) {
/**
* Get a username by ID
* @param int $user_id the user ID
* @param bool $cased if false, return the username in lowercase (default true)
* @return string|null the username, or null if not found
*/
public static function getName( int $user_id ) {
public static function getName( int $user_id, bool $cased = true ) {
$user = SOA2DB::getUserById( $user_id );
return $user ? $user->user_name : null;
return $user ? ($cased ? $user->user_name_cased : $user->user_name) : null;
}
public static function getID( string $user_name ) {
$user = SOA2DB::getUserByName( $user_name );
Expand Down
6 changes: 6 additions & 0 deletions sql/cased_usernames.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BEGIN;

-- Scratch username, case sensitive
ALTER TABLE /*_*/soa2_scratchers ADD COLUMN IF NOT EXISTS user_name_cased varchar(20) binary UNIQUE;

COMMIT;