Skip to content

Commit

Permalink
fix: authenticate weblate requests (#6790)
Browse files Browse the repository at this point in the history
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
  • Loading branch information
SethFalco and repo-ranger[bot] authored Jul 25, 2021
1 parent 1e72d5e commit bd6f4ee
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 36 deletions.
4 changes: 4 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"TWITCH_CLIENT_SECRET": {
"description": "Configure the client secret to be used for the Twitch service.",
"required": false
},
"WEBLATE_API_KEY": {
"description": "Configure the API key to be used for the Weblate service.",
"required": false
}
},
"formation": {
Expand Down
3 changes: 3 additions & 0 deletions config/custom-environment-variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public:
authorizedOrigins: 'SONAR_ORIGINS'
teamcity:
authorizedOrigins: 'TEAMCITY_ORIGINS'
weblate:
authorizedOrigins: 'WEBLATE_ORIGINS'
trace: 'TRACE_SERVICES'

cacheHeaders:
Expand Down Expand Up @@ -95,4 +97,5 @@ private:
wheelmap_token: 'WHEELMAP_TOKEN'
influx_username: 'INFLUX_USERNAME'
influx_password: 'INFLUX_PASSWORD'
weblate_api_key: 'WEBLATE_API_KEY'
youtube_api_key: 'YOUTUBE_API_KEY'
2 changes: 2 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public:
debug:
enabled: false
intervalSeconds: 200
weblate:
authorizedOrigins: 'https://hosted.weblate.org'
trace: false

cacheHeaders:
Expand Down
1 change: 1 addition & 0 deletions config/local-shields-io-production.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ private:
sl_insight_apiToken: ...
twitch_client_id: ...
twitch_client_secret: ...
weblate_api_key: ...
wheelmap_token: ...
youtube_api_key: ...
1 change: 1 addition & 0 deletions config/local.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ private:
gh_token: '...'
twitch_client_id: '...'
twitch_client_secret: '...'
weblate_api_key: '...'
wheelmap_token: '...'
youtube_api_key: '...'
2 changes: 2 additions & 0 deletions core/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const publicConfigSchema = Joi.object({
npm: defaultService,
sonar: defaultService,
teamcity: defaultService,
weblate: defaultService,
trace: Joi.boolean().required(),
}).required(),
cacheHeaders: { defaultCacheLengthSeconds: nonNegativeInteger },
Expand Down Expand Up @@ -182,6 +183,7 @@ const privateConfigSchema = Joi.object({
wheelmap_token: Joi.string(),
influx_username: Joi.string(),
influx_password: Joi.string(),
weblate_api_key: Joi.string(),
youtube_api_key: Joi.string(),
}).required()
const privateMetricsInfluxConfigSchema = privateConfigSchema.append({
Expand Down
15 changes: 15 additions & 0 deletions doc/server-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ access to your private nexus repositories.
Register an application in the [Twitch developer console](https://dev.twitch.tv/console)
in order to obtain a client id and a client secret for making Twitch API calls.

### Weblate

- `WEBLATE_ORIGINS` (yml: `public.services.weblate.authorizedOrigins`)
- `WEBLATE_API_KEY` (yml: `private.weblate_api_key`)

By default Weblate throttles [unauthenticated request][weblate authentication]
to only 100 requests per day, after this you will need an API key or else
badges will stop working.

You can find your Weblate API key in your profile under
["API access"][weblate api key location].

[weblate authentication]: https://docs.weblate.org/en/latest/api.html#authentication-and-generic-parameters
[weblate api key location]: https://hosted.weblate.org/accounts/profile/#api

### Wheelmap

- `WHEELMAP_TOKEN` (yml: `private.wheelmap_token`)
Expand Down
21 changes: 21 additions & 0 deletions services/weblate/weblate-base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import { optionalUrl } from '../validators.js'

export default class WeblateBase extends BaseJsonService {
static queryParamSchema = Joi.object({
server: optionalUrl,
}).required()

static auth = {
passKey: 'weblate_api_key',
isRequired: false,
serviceKey: 'weblate',
}

async fetch(requestParams) {
return this._requestJson(
this.authHelper.withBearerAuthHeader(requestParams, 'Token')
)
}
}
14 changes: 5 additions & 9 deletions services/weblate/weblate-component-license.service.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import { optionalUrl } from '../validators.js'
import WeblateBase from './weblate-base.js'

const schema = Joi.object({
license: Joi.string().required(),
}).required()

const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()

/**
* This badge displays the license of a component on a Weblate instance.
*/
export default class WeblateComponentLicense extends BaseJsonService {
export default class WeblateComponentLicense extends WeblateBase {
static category = 'license'

static route = {
base: 'weblate/l',
pattern: ':project/:component',
queryParamSchema,
queryParamSchema: this.queryParamSchema,
}

static examples = [
Expand All @@ -38,7 +34,7 @@ export default class WeblateComponentLicense extends BaseJsonService {
}

async fetch({ project, component, server = 'https://hosted.weblate.org' }) {
return this._requestJson({
return super.fetch({
schema,
url: `${server}/api/components/${project}/${component}/`,
errorMessages: {
Expand Down
15 changes: 6 additions & 9 deletions services/weblate/weblate-entities.service.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import { nonNegativeInteger, optionalUrl } from '../validators.js'
import { nonNegativeInteger } from '../validators.js'
import { metric } from '../text-formatters.js'
import WeblateBase from './weblate-base.js'

const schema = Joi.object({
count: nonNegativeInteger,
}).required()

const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()

export default class WeblateEntities extends BaseJsonService {
export default class WeblateEntities extends WeblateBase {
static category = 'other'

static route = {
base: 'weblate',
pattern: ':type(components|projects|users|languages)',
queryParamSchema,
queryParamSchema: this.queryParamSchema,
}

static examples = [
Expand All @@ -36,7 +33,7 @@ export default class WeblateEntities extends BaseJsonService {
}

async fetch({ type, server = 'https://hosted.weblate.org' }) {
return this._requestJson({
return super.fetch({
schema,
url: `${server}/api/${type}/`,
errorMessages: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import { optionalUrl } from '../validators.js'
import { colorScale } from '../color-formatters.js'
import WeblateBase from './weblate-base.js'

const schema = Joi.object({
translated_percent: Joi.number().required(),
}).required()

const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()

/**
* This badge displays the percentage of strings translated on a project on a
* Weblate instance.
*/
export default class WeblateProjectTranslatedPercentage extends BaseJsonService {
export default class WeblateProjectTranslatedPercentage extends WeblateBase {
static category = 'other'

static route = {
base: 'weblate/progress',
pattern: ':project',
queryParamSchema,
queryParamSchema: this.queryParamSchema,
}

static examples = [
Expand Down Expand Up @@ -50,7 +46,7 @@ export default class WeblateProjectTranslatedPercentage extends BaseJsonService
}

async fetch({ project, server = 'https://hosted.weblate.org' }) {
return this._requestJson({
return super.fetch({
schema,
url: `${server}/api/projects/${project}/statistics/`,
errorMessages: {
Expand Down
15 changes: 6 additions & 9 deletions services/weblate/weblate-user-statistic.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import { nonNegativeInteger, optionalUrl } from '../validators.js'
import { nonNegativeInteger } from '../validators.js'
import { metric } from '../text-formatters.js'
import WeblateBase from './weblate-base.js'

const schema = Joi.object({
translated: nonNegativeInteger,
Expand All @@ -11,10 +11,6 @@ const schema = Joi.object({
languages: nonNegativeInteger,
}).required()

const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()

const statisticKeyNames = {
translations: 'translated',
suggestions: 'suggested',
Expand All @@ -23,13 +19,14 @@ const statisticKeyNames = {
languages: 'languages',
}

export default class WeblateUserStatistic extends BaseJsonService {
export default class WeblateUserStatistic extends WeblateBase {
static category = 'other'

static route = {
base: 'weblate',
pattern:
':statistic(translations|suggestions|languages|uploads|comments)/:user',
queryParamSchema,
queryParamSchema: this.queryParamSchema,
}

static examples = [
Expand All @@ -49,7 +46,7 @@ export default class WeblateUserStatistic extends BaseJsonService {
}

async fetch({ user, server = 'https://hosted.weblate.org' }) {
return this._requestJson({
return super.fetch({
schema,
url: `${server}/api/users/${user}/statistics/`,
errorMessages: {
Expand Down

0 comments on commit bd6f4ee

Please sign in to comment.