Skip to content

Commit

Permalink
Update token system to reflect latest MediaWiki (#67)
Browse files Browse the repository at this point in the history
This resolves #45, resolves #46, and resolves part of #65.
  • Loading branch information
elifoster committed Oct 17, 2017
1 parent fe6edf4 commit a6bc463
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 80 deletions.
4 changes: 2 additions & 2 deletions lib/mediawiki/administration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def block(user, expiry = '2 weeks', reason = nil, nocreate = true)
expiry: expiry
}

token = get_token('block')
token = get_token
params[:reason] = reason if reason
params[:nocreate] = '1' if nocreate
params[:token] = token
Expand All @@ -43,7 +43,7 @@ def unblock(user, reason = nil)
action: 'unblock',
user: user
}
token = get_token('unblock')
token = get_token
params[:reason] = reason if reason
params[:token] = token

Expand Down
51 changes: 11 additions & 40 deletions lib/mediawiki/auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,23 @@ module Auth
# Logs the user into the wiki. This is generally required for editing and getting restricted data.
# @param username [String] The username
# @param password [String] The password
# @param token [String] The login token to use. Only set this if you know what you are doing. You probably want
# to just let the function get the token and set it on its own.
# @see #check_login
# @see https://www.mediawiki.org/wiki/API:Login MediaWiki Login API Docs
# @since 0.1.0
# @raise [AuthenticationError]
# @return [Boolean] True if the login was successful.
def login(username, password, token = nil)
def login(username, password)
params = {
action: 'login',
lgname: username,
lgpassword: password
lgpassword: password,
lgtoken: get_token('login')
}
params[:lgtoken] = token if token
header = {}
header['Set-Cookie'] = @cookie if @cookie

response = post(params, true, header, true)
response = post(params)
result = response['login']['result']

if result == 'NeedToken'
token = response['login']['token']
return login(username, password, token)
end

if result == 'Success'
@cookie = "#{response['login']['cookieprefix']}Session=#{response['login']['sessionid']}"
@name = username
@name = response['login']['lgusername']
@logged_in = true
return true
end
Expand Down Expand Up @@ -65,18 +54,16 @@ def logout
# @param language [String] The language code to be set as default for the account. Defaults to 'en', or English.
# Use the language code, not the name.
# @param reason [String] The reason for creating the account, as shown in the account creation log. Optional.
# @param token [String] The account creation token to use. Only set this if you know what you are doing. You
# probably want to just let the function get the token and set it on its own.
# @see #check_create
# @see https://www.mediawiki.org/wiki/API:Account_creation MediaWiki Account Creation Docs
# @since 0.1.0
# @return [Boolean] True if successful, false if not.
def create_account(username, password, language = 'en', reason = nil, token = '')
def create_account(username, password, language = 'en', reason = nil)
params = {
name: username,
password: password,
language: language,
token: token
token: get_token('createaccount')
}
params[:reason] = reason unless reason.nil?

Expand All @@ -85,15 +72,7 @@ def create_account(username, password, language = 'en', reason = nil, token = ''
raise MediaWiki::Butt::AuthenticationError.new(result['error']['code'])
end

if result['createaccount']['result'] == 'Success'
@tokens.clear

return true
elsif result['createaccount']['result'] == 'NeedToken'
return create_account(username, password, language, reason, result['createaccount']['token'])
end

false
result['createaccount']['result'] == 'Success'
end

# Creates an account using the random password sent by email procedure.
Expand All @@ -103,13 +82,13 @@ def create_account(username, password, language = 'en', reason = nil, token = ''
# @see https://www.mediawiki.org/wiki/API:Account_creation MediaWiki Account Creation Docs
# @since 0.1.0
# @return [Boolean] True if successful, false if not.
def create_account_email(username, email, language = 'en', reason = nil, token = '')
def create_account_email(username, email, language = 'en', reason = nil)
params = {
name: username,
email: email,
mailpassword: 'value',
language: language,
token: token
token: get_token('createaccount')
}
params[:reason] = reason unless reason.nil?

Expand All @@ -118,15 +97,7 @@ def create_account_email(username, email, language = 'en', reason = nil, token =
raise MediaWiki::Butt::AuthenticationError.new(result['error']['code'])
end

if result['createaccount']['result'] == 'Success'
@tokens.clear

return true
elsif result['createaccount']['result'] == 'NeedToken'
return create_account_email(username, email, language, reason, result['createaccount']['token'])
end

false
result['createaccount']['result'] == 'Success'
end
end
end
15 changes: 6 additions & 9 deletions lib/mediawiki/edit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def edit(title, text, opts = {})
text: text,
nocreate: 1,
format: 'json',
token: get_token('edit', title)
token: get_token
}

params[:summary] ||= opts[:summary]
Expand Down Expand Up @@ -63,7 +63,7 @@ def create_page(title, text, opts = {})
summary: opts[:summary],
createonly: 1,
format: 'json',
token: get_token('edit', title)
token: get_token
}

params[:bot] = '1' if opts[:bot]
Expand All @@ -90,7 +90,7 @@ def upload(url, filename = nil)
params = {
action: 'upload',
url: url,
format: 'json'
token: get_token
}

filename = filename.nil? ? url.split('/')[-1] : filename.sub(/^File:/, '')
Expand All @@ -99,9 +99,7 @@ def upload(url, filename = nil)
allowed_extensions = get_allowed_file_extensions
raise MediaWiki::Butt::UploadInvalidFileExtError.new unless allowed_extensions.include?(ext)

token = get_token('edit', filename)
params[:filename] = filename
params[:token] = token

response = post(params)

Expand Down Expand Up @@ -133,7 +131,7 @@ def move(from, to, opts = {})
action: 'move',
from: from,
to: to,
token: get_token('move', from)
token: get_token
}

params[:reason] ||= opts[:reason]
Expand All @@ -158,12 +156,11 @@ def move(from, to, opts = {})
def delete(title, reason = nil)
params = {
action: 'delete',
title: title
title: title,
token: get_token
}

token = get_token('delete', title)
params[:reason] = reason unless reason.nil?
params[:token] = token

response = post(params)
return true if response['delete']
Expand Down
27 changes: 27 additions & 0 deletions lib/mediawiki/query/meta/meta.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ module Meta
include MediaWiki::Query::Meta::UserInfo
include MediaWiki::Query::Meta::FileRepoInfo
include MediaWiki::Query::Meta::UserInfo

# All valid types of tokens. Taken from API:Tokens on MediaWiki.
TOKEN_TYPES = %w(csrf watch patrol rollback userrights login createaccount)

# Obtains a token for the current user (or lack thereof) for specific actions. This uses the functionality
# introduced in MediaWiki 1.27
# @param type [String, Array<String>] The type of token to get. See #TOKEN_TYPES to see the valid types. If it
# is invalid, it will default to 'csrf'. If it is an array, it will join by a pipe for the API.
# @return [String, Hash<String => String>] Either a token or a set of tokens organized by type. If multiple
# valid types are provided in the parameter, it returns a hash identical to the API response (see API docs).
def get_token(type = 'csrf')
params = {
action: 'query',
meta: 'tokens'
}

if type.is_a?(Array)
type = (type - TOKEN_TYPES).empty? ? type.join('|') : 'csrf'
else
type = TOKEN_TYPES.include?(type) ? type : 'csrf'
end
params[:type] = type

resp = post(params)
tokens = resp['query']['tokens']
tokens.size > 1 ? tokens : tokens["#{type}token"]
end
end
end
end
29 changes: 0 additions & 29 deletions lib/mediawiki/query/properties/properties.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,6 @@ module Properties
include MediaWiki::Query::Properties::Contributors
include MediaWiki::Query::Properties::Pages
include MediaWiki::Query::Properties::Files

# Gets the token for the given type. This method should rarely be used by normal users.
# @param type [String] The type of token.
# @param title [String] The page title for the token. Optional.
# @see https://www.mediawiki.org/wiki/API:Info MediaWiki Info API Docs
# @since 0.5.0
# @return [String] The token. If the butt isn't logged in, it returns with '+\\'.
def get_token(type, title = nil)
return '+\\' unless @logged_in

# There is some weird thing with MediaWiki where you must pass a valid inprop parameter in order to get any
# response at all. This is why there is a displaytitle inprop as well as gibberish in the titles parameter.
# And to avoid normalization, it's capitalized.
params = {
action: 'query',
prop: 'info',
inprop: 'displaytitle',
intoken: type
}

title = 'Somegibberish' if title.nil?
params[:titles] = title
response = post(params)
revid = nil
response['query']['pages'].each { |r, _| revid = r }

# URL encoding is not needed for some reason.
response['query']['pages'][revid]["#{type}token"]
end
end
end
end

0 comments on commit a6bc463

Please sign in to comment.