Skip to content

Commit 3351d96

Browse files
authored
Merge pull request #501 from topcoder-platform/develop
nested group upgrades
2 parents 3cbaf79 + 409d976 commit 3351d96

File tree

48 files changed

+625
-520
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+625
-520
lines changed

.exchange-rates.cache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"disclaimer":"Usage subject to terms: https://openexchangerates.org/terms","license":"https://openexchangerates.org/license","timestamp":1506333600,"base":"USD","rates":{"AED":3.673158,"AFN":68.6465,"ALL":112.58,"AMD":479.63649,"ANG":1.785999,"AOA":165.9215,"ARS":17.3005,"AUD":1.25734,"AWG":1.794996,"AZN":1.7,"BAM":1.639912,"BBD":2,"BDT":82.238586,"BGN":1.644233,"BHD":0.377199,"BIF":1754.926108,"BMD":1,"BND":1.349018,"BOB":6.998006,"BRL":3.125,"BSD":1,"BTC":0.000265269665,"BTN":64.934734,"BWP":10.197008,"BYN":1.942719,"BZD":2.022299,"CAD":1.232918,"CDF":1562.881563,"CHF":0.973363,"CLF":0.02322,"CLP":627.82,"CNH":6.614113,"CNY":6.621016,"COP":2905.8,"CRC":576.881761,"CUC":1,"CUP":25.5,"CVE":92.675,"CZK":21.899438,"DJF":178.57,"DKK":6.259235,"DOP":47.311859,"DZD":112.421483,"EGP":17.668,"ERN":15.340012,"ETB":23.42892,"EUR":0.841295,"FJD":2.011699,"FKP":0.739307,"GBP":0.739307,"GEL":2.4777,"GGP":0.739307,"GHS":4.4175,"GIP":0.739307,"GMD":45.97,"GNF":8979.55,"GTQ":7.319581,"GYD":206.814115,"HKD":7.812934,"HNL":23.470563,"HRK":6.2963,"HTG":63.622543,"HUF":261.175784,"IDR":13329.280094,"ILS":3.51128,"IMP":0.739307,"INR":65.09,"IQD":1170.400369,"IRR":33402.5,"ISK":107.805414,"JEP":0.739307,"JMD":130.83531,"JOD":0.709101,"JPY":112.0615,"KES":103.225,"KGS":68.451752,"KHR":4077.641667,"KMF":412.6,"KPW":900,"KRW":1131.7025,"KWD":0.301675,"KYD":0.836119,"KZT":342.36841,"LAK":8310.85,"LBP":1508.862443,"LKR":153.01,"LRD":117.254872,"LSL":13.248849,"LYD":1.360769,"MAD":9.37926,"MDL":17.639888,"MGA":3056.925758,"MKD":51.812066,"MMK":1368.61006,"MNT":2460.413333,"MOP":8.070913,"MRO":365.964861,"MUR":33.475,"MVR":15.409873,"MWK":725.52,"MXN":17.795665,"MYR":4.198771,"MZN":62.012392,"NAD":13.248849,"NGN":358.522572,"NIO":30.342742,"NOK":7.823037,"NPR":103.982045,"NZD":1.37505,"OMR":0.38502,"PAB":1,"PEN":3.246393,"PGK":3.205299,"PHP":50.6885,"PKR":105.715129,"PLN":3.592565,"PYG":5707.227124,"QAR":3.65395,"RON":3.868876,"RSD":100.579362,"RUB":57.3153,"RWF":834.26744,"SAR":3.7502,"SBD":7.746542,"SCR":13.150523,"SDG":6.699279,"SEK":8.025323,"SGD":1.350376,"SHP":0.739307,"SLL":7550,"SOS":580.12834,"SRD":7.438,"SSP":126.6773,"STD":20559.200196,"SVC":8.778896,"SYP":514.98999,"SZL":13.24451,"THB":33.12,"TJS":8.839108,"TMT":3.499986,"TND":2.452101,"TOP":2.21298,"TRY":3.518075,"TTD":6.798325,"TWD":30.224452,"TZS":2244.2,"UAH":26.338725,"UGX":3637.566138,"USD":1,"UYU":28.969536,"UZS":8109.75,"VEF":9.985022,"VND":22745.133333,"VUV":104.150397,"WST":2.491006,"XAF":551.853344,"XAG":0.05893621,"XAU":0.00077184,"XCD":2.70255,"XDR":0.702884,"XOF":551.853344,"XPD":0.0010835,"XPF":100.393198,"XPT":0.00106785,"YER":250.25,"ZAR":13.26789,"ZMW":9.536229,"ZWL":322.355011}}
1+
{"disclaimer":"Usage subject to terms: https://openexchangerates.org/terms","license":"https://openexchangerates.org/license","timestamp":1506589200,"base":"USD","rates":{"AED":3.673097,"AFN":68.606,"ALL":113.74,"AMD":477.825,"ANG":1.779333,"AOA":165.9215,"ARS":17.556,"AUD":1.277596,"AWG":1.794996,"AZN":1.7,"BAM":1.664404,"BBD":2,"BDT":82.368,"BGN":1.66431,"BHD":0.377193,"BIF":1747.6,"BMD":1,"BND":1.359115,"BOB":6.96234,"BRL":3.193001,"BSD":1,"BTC":0.000234408252,"BTN":65.735583,"BWP":10.380039,"BYN":1.960654,"BZD":2.014853,"CAD":1.248048,"CDF":1562.881563,"CHF":0.973886,"CLF":0.0237,"CLP":638.5,"CNH":6.66795,"CNY":6.671014,"COP":2936.05,"CRC":573.445,"CUC":1,"CUP":25.5,"CVE":94,"CZK":22.140263,"DJF":178.77,"DKK":6.3243,"DOP":47.172224,"DZD":113.195,"EGP":17.682997,"ERN":15.323865,"ETB":23.600634,"EUR":0.849878,"FJD":2.037546,"FKP":0.748453,"GBP":0.748453,"GEL":2.4766,"GGP":0.748453,"GHS":4.525803,"GIP":0.748453,"GMD":46.125,"GNF":8954.4,"GTQ":7.320779,"GYD":208.92,"HKD":7.809138,"HNL":23.380424,"HRK":6.375305,"HTG":63.048705,"HUF":264.3815,"IDR":13462.096354,"ILS":3.53394,"IMP":0.748453,"INR":65.615,"IQD":1166.55,"IRR":33482.5,"ISK":106.91,"JEP":0.748453,"JMD":129.802793,"JOD":0.708801,"JPY":112.78455556,"KES":103.35,"KGS":68.430613,"KHR":4050.3,"KMF":419.069527,"KPW":900,"KRW":1147.7925,"KWD":0.302145,"KYD":0.832951,"KZT":340.215,"LAK":8291.1,"LBP":1507.45,"LKR":153.14,"LRD":117.505705,"LSL":13.534319,"LYD":1.3632,"MAD":9.437738,"MDL":17.624343,"MGA":3024.15,"MKD":52.385755,"MMK":1362.9,"MNT":2458.51808,"MOP":8.042813,"MRO":364.855,"MUR":33.832,"MVR":15.400126,"MWK":726.822859,"MXN":18.203515,"MYR":4.230478,"MZN":61.841595,"NAD":13.534569,"NGN":357.355,"NIO":30.332268,"NOK":7.964293,"NPR":105.06,"NZD":1.390221,"OMR":0.384992,"PAB":1,"PEN":3.273541,"PGK":3.201069,"PHP":50.935,"PKR":105.37,"PLN":3.66838,"PYG":5669.15,"QAR":3.6415,"RON":3.906405,"RSD":101.5,"RUB":58.244,"RWF":845.27,"SAR":3.750245,"SBD":7.802738,"SCR":13.596666,"SDG":6.673942,"SEK":8.136983,"SGD":1.361723,"SHP":0.748453,"SLL":7538.795349,"SOS":578.24,"SRD":7.438,"SSP":126.8343,"STD":20836.810788,"SVC":8.746669,"SYP":514.92999,"SZL":13.536834,"THB":33.37,"TJS":8.791467,"TMT":3.499986,"TND":2.466705,"TOP":2.245611,"TRY":3.575301,"TTD":6.78024,"TWD":30.345708,"TZS":2245.3,"UAH":26.461997,"UGX":3603.6,"USD":1,"UYU":28.873646,"UZS":8063.9,"VEF":10.10075,"VND":22730.535743,"VUV":105.58901,"WST":2.515803,"XAF":557.483173,"XAG":0.05970514,"XAU":0.00077997,"XCD":2.70255,"XDR":0.708837,"XOF":557.483173,"XPD":0.00107357,"XPF":101.417377,"XPT":0.00108757,"YER":250.256642,"ZAR":13.598095,"ZMW":9.611001,"ZWL":322.355011}}

__tests__/server/tc-communities.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import request from 'supertest';
22

33
const MODULE = require.resolve('server/server');
44

5-
describe('tc-communities api test', () => {
5+
describe.skip('tc-communities api test', () => {
66
let server;
77
beforeEach(() => {
88
jest.resetModules();

__tests__/shared/actions/tc-communities/meta.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('tcCommunities.meta.fetchDataInit', () => {
3939
expect(a.payload).toBeUndefined());
4040
});
4141

42-
describe('tcCommunities.meta.fetchDataDone', () => {
42+
describe.skip('tcCommunities.meta.fetchDataDone', () => {
4343
const a = actions.tcCommunities.meta.fetchDataDone('someId');
4444

4545
test('has expected type', () => {
@@ -55,7 +55,7 @@ describe('tcCommunities.meta.fetchDataDone', () => {
5555
expect(a404.type).toBe('TC_COMMUNITIES/META/FETCH_DATA_DONE');
5656
});
5757

58-
test('payload is a promise which rejects to the expected object', () =>
58+
test.skip('payload is a promise which rejects to the expected object', () =>
5959
a404.payload.catch(err => expect(err).toEqual({ communityId: 'someId404', error: '404' })));
6060
});
6161

@@ -72,11 +72,11 @@ describe('tcCommunities.meta.fetchDataDone at frontend', () => {
7272
expect(a.type).toBe('TC_COMMUNITIES/META/FETCH_DATA_DONE');
7373
});
7474

75-
test('payload is a promise which resolves to the expected object', () =>
75+
test.skip('payload is a promise which resolves to the expected object', () =>
7676
a.payload.then(res => expect(res).toEqual('dummy')));
7777
});
7878

79-
describe('tcCommunities.meta.fetchDataDone at frontend with 404 response', () => {
79+
describe.skip('tcCommunities.meta.fetchDataDone at frontend with 404 response', () => {
8080
global.fetch = jest.fn(() => Promise.resolve({
8181
status: 404,
8282
json: () => 'dummy',

__tests__/shared/components/challenge-listing/Filters/__snapshots__/ChallengeFilters.jsx.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ exports[`Matches shallow shapshot shapshot 1`] = `
5050
}
5151
communityName="name"
5252
filterState={Object {}}
53-
groupId={undefined}
5453
hidden={true}
5554
isSavingFilter={false}
5655
onClose={[Function]}
@@ -205,7 +204,6 @@ exports[`Matches shallow shapshot shapshot 2`] = `
205204
],
206205
}
207206
}
208-
groupId={undefined}
209207
hidden={true}
210208
isSavingFilter={false}
211209
onClose={[Function]}

__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ exports[`Matches shallow shapshot 1 shapshot 1 1`] = `
77
>
88
<Connect(Container)
99
communityName={null}
10-
groupId=""
1110
isCardTypeSet="Challenges"
1211
setCardType={[Function]}
1312
/>
@@ -76,7 +75,6 @@ exports[`Matches shallow shapshot 1 shapshot 1 1`] = `
7675
communityName={null}
7776
currentFilterName=""
7877
expanded={false}
79-
groupId=""
8078
loadMoreDraft={null}
8179
loadMorePast={null}
8280
loadingDraftChallenges={false}
@@ -121,7 +119,6 @@ exports[`Matches shallow shapshot 2 shapshot 2 1`] = `
121119
>
122120
<Connect(Container)
123121
communityName={null}
124-
groupId=""
125122
isCardTypeSet="Challenges"
126123
setCardType={[Function]}
127124
/>

__tests__/shared/components/tc-communities/__snapshots__/Header.jsx.snap

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ exports[`Snapshot match 1`] = `
1616
},
1717
]
1818
}
19-
groupId=""
19+
groupIds={
20+
Array [
21+
"",
22+
]
23+
}
2024
hideJoinNow={false}
2125
hideSearch={false}
2226
isMobileOpen={false}
@@ -78,7 +82,11 @@ exports[`Snapshot match 2`] = `
7882
]
7983
}
8084
cssUrl="some/css/url"
81-
groupId=""
85+
groupIds={
86+
Array [
87+
"",
88+
]
89+
}
8290
hideJoinNow={false}
8391
hideSearch={false}
8492
isMobileOpen={true}

__tests__/shared/components/tc-communities/__snapshots__/JoinCommunity.jsx.snap

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ exports[`Matches shallow shapshot 1`] = `
1010
</button>
1111
<ConfirmModal
1212
communityName="ios"
13-
groupId="1"
13+
groupIds={
14+
Array [
15+
"",
16+
]
17+
}
1418
join={[Function]}
1519
resetJoinButton={[Function]}
1620
token="token"
@@ -99,7 +103,11 @@ exports[`Matches shallow shapshot 5`] = `
99103
</button>
100104
<ConfirmModal
101105
communityName="ios"
102-
groupId="1"
106+
groupIds={
107+
Array [
108+
"",
109+
]
110+
}
103111
join={[Function]}
104112
resetJoinButton={[Function]}
105113
token={null}

__tests__/shared/containers/tc-communities/CommunityStats.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ describe('full render connnected component and dispatch actions', () => {
2121
const initialState = {
2222
tcCommunities: {
2323
meta: {
24-
communityId: '1',
24+
data: {
25+
communityId: '1',
26+
},
2527
},
2628
},
2729
icon: 'lorem',

__tests__/shared/containers/tc-communities/JoinCommunity.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ describe('full render connnected component and dispatch actions', () => {
2222
const initialState = {
2323
tcCommunities: {
2424
meta: {
25-
challengeGroupId: '1',
26-
communityName: 'name',
25+
data: {
26+
challengeGroupId: '1',
27+
communityName: 'name',
28+
},
2729
},
2830
hideJoinButton: true,
2931
joinCommunityButton: 'joined',

__tests__/shared/reducers/tc-communities/meta.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ function testReducer(reducer, istate) {
2929
test('Handles fetchDataInit as expected', () => {
3030
state = reducer(state, mockMetaActions.tcCommunities.meta.fetchDataInit());
3131
expect(state).toEqual({
32+
data: {},
3233
lastUpdateOfMetaData: 0,
3334
loadingMetaDataForCommunityId: 'test-community',
3435
});
@@ -44,6 +45,7 @@ function testReducer(reducer, istate) {
4445
}
4546

4647
const INITIAL_STATE = {
48+
data: {},
4749
lastUpdateOfMetaData: 0,
4850
loadingMetaDataForCommunityId: '',
4951
};

config/default.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
* due to caching). */
5757
"REAUTH_TIME": 55,
5858

59+
"SWIFT_PROGRAM_ID": 3445,
60+
5961
/* Various URLs. Most of them lead to different segments of Topcoder
6062
* platform. */
6163
"URL": {
@@ -98,5 +100,9 @@
98100
"USER_SETTINGS": "https://lc1-user-settings-service.herokuapp.com",
99101
"WIPRO": "https://wipro.topcoder.com"
100102
},
101-
"SWIFT_PROGRAM_ID": 3445
103+
104+
/* Information about Topcoder user groups can be cached in various places.
105+
* This value [seconds] specifies the maximum age after which a group data
106+
* object should be considered outdated, and updated as soon as possible. */
107+
"USER_GROUP_MAXAGE": 600
102108
}

docs/how-to-add-a-new-topcoder-community.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ To add a new community with the name **demo**, we should follow the following pr
77
2. Community meta-data file should be created under the path `/src/server/tc-communities/demo/metadata.json`:
88
```json
99
{
10-
"authorizedGroupIds": [
11-
"12345"
12-
],
10+
"authorizedGroupIds": ["12345"],
1311
"challengeFilter": {
1412
"groupIds": ["12345"]
1513
},
@@ -27,7 +25,7 @@ To add a new community with the name **demo**, we should follow the following pr
2725
"redirect": "https://ios.topcoder.com/",
2826
"value": "3"
2927
}],
30-
"groupId": "12345",
28+
"groupIds": ["12345"],
3129
"leaderboardApiUrl": "https://api.topcoder.com/v4/looks/0/run/json/",
3230
"logos": [
3331
"/themes/demo/logo_topcoder_with_name.svg"
@@ -58,7 +56,12 @@ To add a new community with the name **demo**, we should follow the following pr
5856
}
5957
```
6058
Its fields serve the following purposes:
61-
- `authorizedGroupIds` - *String Array* - Optional. Array of group IDs. If specified, access to the community will be restricted only to authenticated visitors, included into, at least, one of the groups listed in this array. If undefined, community will be accessible to any visitors (including non-authenticated ones).
59+
60+
> Note that we have three places where user groups can be mentioned in this config: `authorizedGroupIds` (Optional) controls authorizations necessary to access community; `groupIds` controls who is considered to be a member of community; and `groupIds` (Optional) inside `challengeFilter` allows to filter challenges included into community by their user group affinity.
61+
>
62+
> Technically, when application server serves configuration object for a specified community, it extends each of these arrays by descendant groups (it helps to significantly simply a lot of related code).
63+
64+
- `authorizedGroupIds` - *String Array* - Optional. Array of group IDs. If specified, access to the community will be restricted only to authenticated visitors, included into any of these groups, or any of their descendant groups. If undefined, community will be accessible to any visitors (including non-authenticated ones).
6265
- `challengeFilter` - *Object* - Challenge filter matching challenges related to the community. This object can include any options known to the `/src/utils/challenge-listing/filter.js` module, though in many cases you want to use just one of these:
6366
```js
6467
/* Matches challenges belonging to any of the groups listed by ID. */
@@ -88,7 +91,7 @@ To add a new community with the name **demo**, we should follow the following pr
8891
- `points` - Points are shown rather than the prizes. The points are taken from `drPoints` field of challenge objects. There is no prizes tooltip in this case.
8992
- `communityId` - *String* - Unique ID of this community.
9093
- `communitySelector` - *Object Array* - Specifies data for the community selection dropdown inside the community header. Each object MUST HAVE `label` and `value` string fields, and MAY HAVE `redirect` field. If `redirect` field is specified, a click on that option in the dropdown will redirect user to the specified URL.
91-
- `groupId` - *String* - Main user group of the community. All members of this group, and its descendant groups are treated as members of this community. Also, any challenges belonging to these groups are considered to be belonging to the community.
94+
- `groupIds` - *String Array* - Community user groups. All members of these groups, or their descendants, will be treated as members of the community. ***Join Community functionality, where available, adds user to the first group from this array. Most probably, this behavior will be updated soon.***
9295
- `leaderboardApiUrl` - *String* - Endpoint from where the leaderboard data should be loaded.
9396
- `logos` - *String Array | Object Array* - Array of image URLs to insert as logos into the left corner of community's header, alternatively the array may contain JS objects of shape
9497
```

src/client/index.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import actions from 'actions/auth';
6+
import userGroupsActions from 'actions/groups';
67
import cookies from 'browser-cookies';
78
import { BrowserRouter, browserHistory } from 'react-router-dom';
89
import React from 'react';
@@ -65,6 +66,12 @@ function authenticate(store) {
6566
store.dispatch(actions.auth.setTcTokenV2(tctV2));
6667
}
6768

69+
/* User group data demands proper authorization to be accessed,
70+
* thus they should be dropped if authentication fails. */
71+
if (!tctV3) {
72+
store.dispatch(userGroupsActions.groups.dropGroups());
73+
}
74+
6875
/* Automatic refreshment of auth tokens. */
6976
let time = Number.MAX_VALUE;
7077
if (tctV2) time = decodeToken(tctV2).exp;

0 commit comments

Comments
 (0)