5 /* global Uint16Array */
7 var userInfoPromise
, pageviewRandomId
;
10 * Get the current user's groups or rights
13 * @return {jQuery.Promise}
15 function getUserInfo() {
16 if ( !userInfoPromise
) {
17 userInfoPromise
= new mw
.Api().getUserInfo();
19 return userInfoPromise
;
22 // mw.user with the properties options and tokens gets defined in mediawiki.js.
26 * Generate a random user session ID.
28 * This information would potentially be stored in a cookie to identify a user during a
29 * session or series of sessions. Its uniqueness should not be depended on unless the
30 * browser supports the crypto API.
32 * Known problems with Math.random():
33 * Using the Math.random function we have seen sets
34 * with 1% of non uniques among 200,000 values with Safari providing most of these.
35 * Given the prevalence of Safari in mobile the percentage of duplicates in
36 * mobile usages of this code is probably higher.
39 * We need about 80 bits to make sure that probability of collision
40 * on 155 billion is <= 1%
42 * See https://en.wikipedia.org/wiki/Birthday_attack#Mathematics
43 * n(p;H) = n(0.01,2^80)= sqrt (2 * 2^80 * ln(1/(1-0.01)))
45 * @return {string} 80 bit integer in hex format, padded
47 generateRandomSessionId: function () {
50 crypto
= window
.crypto
|| window
.msCrypto
;
52 if ( crypto
&& crypto
.getRandomValues
&& typeof Uint16Array
=== 'function' ) {
53 // Fill an array with 5 random values, each of which is 16 bits.
54 // Note that Uint16Array is array-like but does not implement Array.
55 rnds
= new Uint16Array( 5 );
56 crypto
.getRandomValues( rnds
);
58 rnds
= new Array( 5 );
59 // 0x10000 is 2^16 so the operation below will return a number
60 // between 2^16 and zero
61 for ( i
= 0; i
< 5; i
++ ) {
62 rnds
[ i
] = Math
.floor( Math
.random() * 0x10000 );
66 // Convert the 5 16bit-numbers into 20 characters (4 hex per 16 bits).
67 // Concatenation of two random integers with entropy n and m
68 // returns a string with entropy n+m if those strings are independent.
69 // Tested that below code is faster than array + loop + join.
70 return ( rnds
[ 0 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
71 ( rnds
[ 1 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
72 ( rnds
[ 2 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
73 ( rnds
[ 3 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
74 ( rnds
[ 4 ] + 0x10000 ).toString( 16 ).slice( 1 );
78 * A sticky generateRandomSessionId for the current JS execution context,
79 * cached within this class (also known as a page view token).
82 * @return {string} 80 bit integer in hex format, padded
84 getPageviewToken: function () {
85 if ( !pageviewRandomId
) {
86 pageviewRandomId
= mw
.user
.generateRandomSessionId();
89 return pageviewRandomId
;
93 * Get the current user's database id
95 * Not to be confused with #id.
97 * @return {number} Current user's id, or 0 if user is anonymous
100 return mw
.config
.get( 'wgUserId' ) || 0;
104 * Get the current user's name
106 * @return {string|null} User name string or null if user is anonymous
108 getName: function () {
109 return mw
.config
.get( 'wgUserName' );
113 * Get date user registered, if available
115 * @return {boolean|null|Date} False for anonymous users, null if data is
116 * unavailable, or Date for when the user registered.
118 getRegistration: function () {
120 if ( mw
.user
.isAnon() ) {
123 registration
= mw
.config
.get( 'wgUserRegistration' );
124 // Registration may be unavailable if the user signed up before MediaWiki
125 // began tracking this.
126 return !registration
? null : new Date( registration
);
130 * Whether the current user is anonymous
134 isAnon: function () {
135 return mw
.user
.getName() === null;
139 * Get an automatically generated random ID (persisted in sessionStorage)
141 * This ID is ephemeral for everyone, staying in their browser only until they
142 * close their browsing session.
144 * @return {string} Random session ID
146 sessionId: function () {
147 var sessionId
= mw
.storage
.session
.get( 'mwuser-sessionId' );
149 sessionId
= mw
.user
.generateRandomSessionId();
150 mw
.storage
.session
.set( 'mwuser-sessionId', sessionId
);
156 * Get the current user's name or the session ID
158 * Not to be confused with #getId.
160 * @return {string} User name or random session ID
163 return mw
.user
.getName() || mw
.user
.sessionId();
167 * Get the current user's groups
169 * @param {Function} [callback]
170 * @return {jQuery.Promise}
172 getGroups: function ( callback
) {
173 var userGroups
= mw
.config
.get( 'wgUserGroups', [] );
175 // Uses promise for backwards compatibility
176 return $.Deferred().resolve( userGroups
).done( callback
);
180 * Get the current user's rights
182 * @param {Function} [callback]
183 * @return {jQuery.Promise}
185 getRights: function ( callback
) {
186 return getUserInfo().then(
187 function ( userInfo
) { return userInfo
.rights
; },
188 function () { return []; }
194 * @method stickyRandomId
195 * @deprecated since 1.32 use getPageviewToken instead
197 mw
.log
.deprecate( mw
.user
, 'stickyRandomId', mw
.user
.getPageviewToken
, 'Please use getPageviewToken instead' );