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

L10n fr #29

Merged
merged 17 commits into from Mar 29, 2015
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 18 additions & 8 deletions credits.js
@@ -1,15 +1,25 @@
var fs = require('fs');
var path = require('path');
var colors = require('colors-tmpl');
var combinedStream = require('combined-stream');

function read (file) {
return fs.createReadStream(path.join(__dirname, file), {encoding: 'utf8'})
}

function credits () {
fs.readFile(path.join(__dirname, './credits.txt'), 'utf8', function (err, data) {
if (err) {
throw err;
}
console.log(colors(data));
});
function credits (workshopper) {
combinedStream
.create()
.append(read ('./i18n/credits/' + workshopper.lang + '.txt'))
.append(read ('./credits.txt'))
.on("error", function (err) {
console.log(err)
throw err
})
.on("data", function (data) {
console.log(colors(data))
})
.resume()
}

module.exports = credits;
module.exports = credits
5 changes: 1 addition & 4 deletions credits.txt
@@ -1,7 +1,4 @@
{yellow}{bold}koaiscool is brought to you by the following persons:{/bold}{/yellow}

{bold}Name GitHub Username{/bold}
-----------------------------------
dead-horse @dead-horse
hemanth.hm @hemanth
Yoshua Wuyts @yoshuawuyts
Christophe Porteneuve @tdd
28 changes: 20 additions & 8 deletions exercise.js
Expand Up @@ -42,7 +42,7 @@ function query(mode) {
// query submisstion server
var submissionUrl = 'http://localhost:' + exercise.submissionPort + task[0];
urllib.request(submissionUrl, task[1], function (err, data, res) {
if (err) return error(err, 'submission');
if (err) return error(err, exercise.__('server_type.submission'));

var verify = task[2];
verify.call(exercise, data, res, exercise.submissionStdout);
Expand All @@ -54,8 +54,7 @@ function query(mode) {
? exercise.solutionPort
: exercise.submissionPort;

var msg = fmt('Error connecting to %s server(http://localhost:%s%s), options: %j. %s',
type, port, task[0], task[1], err.stack);
var msg = fmt(exercise.__('fail.cannot_connect'), type, port, task[0], task[1], err.stack);
exercise.emit('fail', msg);
};
}
Expand All @@ -71,34 +70,47 @@ exports.generate = function () {
// set up the data file to be passed to the submission

exercise.addSetup(function (mode, callback) {
this.submissionCommand.unshift('--harmony');

var self = this;
freeport(function (err, port) {
if (err) throw err;
self.submissionPort = port;

self.submissionCommand = self.submissionCommand.concat([self.submissionPort]).concat(argv);
self.submissionArgs = self.submissionArgs.concat([self.submissionPort]).concat(argv);
if (!self.submissionCommand) {
self.submissionCommand = [ self.submission ].concat(self.submissionArgs);
}
self.submissionCommand.unshift('--harmony');
setImmediate(callback);
});
});

// add a processor for both run and verify calls, added *before*
// the comparestdout processor so we can mess with the stdouts
exercise.addProcessor(function (mode, callback) {

this.submissionStdout.pipe(process.stdout);
// replace stdout with our own streams
this.submissionStdout = through2();
if (mode === 'verify') {
var solutionFile = path.join(this.dir, 'solution/solution.txt');
var solutionFile = path.join(this.dir, 'solution_' + this.lang + '/solution.txt');
if (!fs.existsSync(solutionFile)) {
solutionFile = path.join(this.dir, 'solution/solution.txt');
}

this.solutionStdout = fs.createReadStream(solutionFile);
// this.solutionStdout = fs.createReadStream();
}
setTimeout(query.bind(this, mode), 500);
process.nextTick(callback.bind(null, null, true));
});

exercise.strOut = function strOut(stream, key) {
var args = Array.prototype.slice.call(arguments, 2);
args.unshift(this.__(key));
var result = fmt.apply(null, args);
if ("\n" !== result.slice(-1)) result += "\n";
stream.write(result);
};


// compare stdout of solution and submission
exercise = comparestdout(exercise)
Expand Down
22 changes: 11 additions & 11 deletions exercises/authentication/exercise.js
Expand Up @@ -9,10 +9,10 @@ module.exports = exercise
.push('/', function (data, res, stream) {
if (res.statusCode !== 401) {
console.log(res)
this.emit('fail', 'GET /: non-logged-in user should get 401 error, but got ' + res.statusCode);
this.emit('fail', this.__('fail.no_initial_401', res.statusCode));
process.exit(1);
}
stream.write('GET /: non-logged-in user get 401 error\n');
this.strOut(stream, 'log.initial_401');
})

.push('/login', {
Expand All @@ -23,10 +23,10 @@ module.exports = exercise
}
}, function (data, res, stream) {
if (res.statusCode !== 400) {
this.emit('fail', 'POST /login: incorrect username or password must return 400 error');
this.emit('fail', this.__('fail.no_auth_check'));
process.exit(1);
}
stream.write('POST /login: 400 error when incorrect username or password\n');
this.strOut(stream, 'log.auth_check');
})

.push('/login', {
Expand All @@ -39,38 +39,38 @@ module.exports = exercise
if (!~[302, 303].indexOf(res.statusCode)
|| !res.headers.location
|| res.headers.location !== '/') {
this.emit('fail', 'POST /login: user should be redirected to `/`');
this.emit('fail', this.__('fail.no_login_redirect'));
process.exit(1);
}
headers.cookie = res.headers['set-cookie'].join(';');
stream.write('POST /login: login successed\n');
this.strOut(stream, 'log.login_redirect');
})

.push('/', {
headers: headers
}, function (data, res, stream) {
stream.write('GET /: ' + data.toString() + '\n');
stream.write('GET / : ' + data.toString() + '\n');
})
.push('/logout', {
headers: headers
}, function (data, res, stream) {
if (!~[302, 303].indexOf(res.statusCode)
|| !res.headers.location
|| res.headers.location !== '/login') {
this.emit('fail', 'GET /logout: user should be redirected to `/login`');
this.emit('fail', this.__('fail.no_logout_redirect'));
process.exit(1);
}
headers.cookie = res.headers['set-cookie'].join(';');
stream.write('GET /logout: user is redirected to `/login`\n');
this.strOut(stream, 'log.logout_redirect');
})

.push('/', {
headers: headers
}, function (data, res, stream) {
if (res.statusCode !== 401) {
this.emit('fail', 'GET /: logout user should get 401 error');
this.emit('fail', this.__('fail.no_final_401'));
process.exit(1);
}
stream.write('GET /: logout user get 401 error\n');
this.strOut(stream, 'log.final_401');
})
.generate();
83 changes: 83 additions & 0 deletions exercises/authentication/problem.fr.md
@@ -0,0 +1,83 @@
Dans les exercices précédents, nous avons appris à utiliser les routes,
`body-parser` et `session`. Cette fois-ci, nous allons tenter de combiner
tout ça pour créer une appli très simple avec des fonctionnalités de connexion
et de déconnexion. Nous définirons les routes suivantes :

1) `/`
- Si la personne est loguée, elle devrait voir « Bonjour tout le monde ».
- Sinon, elle aura une erreur 401 faute d’authentification.

2) `/login`
- Avec la méthode GET, affiche un formulaire de connexion.
- Avec la méthode POST, valide le corps de la requête et tente de connecter
la personne ; en cas de connexion réussie, redirige sur `/`.

3) `/logout`
- Déconnecte la personne et redirige sur `/login`.

On ne va pas s’embêter à gérer de véritables comptes utilisateurs pour cet
exercice. La seule authentification que nous accepterons aura les noms et
valeurs de champs suivants :

```
username = username
password = password
```

Toute autre valeur renverra une erreur 400.

## Conseils

Voici un squelette prêt à l’emploi pour cette petite application. Vous n’avez plus
qu’à le compléter.

```
var koa = require('koa');
var parse = require('co-body');
var session = require('koa-session');

var form = '<form action="/login" method="POST">\
<input name="username" type="text" value="username">\
<input name="password" type="password" placeholder="Le mot de passe est \'password\'">\
<button type="submit">Connexion</button>\
</form>';

var app = koa();

// Utilisez koa-session quelque part au début de la pile.
// Nous avons besoin de définir les `.keys` pour les cookies signés
app.keys = ['secret1', 'secret2', 'secret3'];
app.use(session(app));

/**
* Si `this.session.authenticated` existe, la personne voit « Bonjour tout le monde ».
* Dans le cas contraire, elle reçoit une erreur 401, faute d’authentification.
*/
app.use(function* home(next) {
if (this.request.path !== '/') return yield next;

});

/**
* Si la connexion réussit, la personne est authentifiée et redirigée sur `/`.
* Conseil : utilisez `this.redirect(…)`.
*/
app.use(function* login(next) {
if (this.request.path !== '/login') return yield next;

if (this.request.method === 'GET') return this.body = form;

});

/**
* Redirigez sur `/login` quoi qu’il arrive.
* Si une personne va sur `/logout` alors qu’elle est déjà déconnectée, on va
* considérer que ce n’est pas une erreur.
*/
app.use(function* logout(next) {
if (this.request.path !== '/logout') return yield next;

});

app.listen(process.argv[2]);
```
2 changes: 1 addition & 1 deletion exercises/authentication/problem.md
@@ -1,6 +1,6 @@
In previous exercies, we learned `route`, `body-parser` and `session`. In this exercise, we will try to combine them all to create a very simple app with login and logout features. Let's define the following routes:

- `/` - If the user logs in, they should see `hello world`. Otherwise, they should see a `401` error because they aren't logged in.
- `/` - If the user is logged in, they should see `hello world`. Otherwise, they should see a `401` error because they aren't logged in.
- `/login` - if the method is `GET`, a form should be returned. If the method is `POST`, it should validate the request body and attempt to login the user, if login successful redirected to `/`.
- `/logout` - it should logout the user and redirected to `/login`.

Expand Down
12 changes: 6 additions & 6 deletions exercises/authentication/solution/solution.txt
@@ -1,6 +1,6 @@
GET /: non-logged-in user get 401 error
POST /login: 400 error when incorrect username or password
POST /login: login successed
GET /: hello world
GET /logout: user is redirected to `/login`
GET /: logout user get 401 error
GET / : non-logged-in user get 401 error
POST /login : 400 error when incorrect username or password
POST /login : login successful
GET / : hello world
GET /logout : user is redirected to `/login`
GET / : logged-out user get 401 error
61 changes: 61 additions & 0 deletions exercises/authentication/solution_fr/solution.js
@@ -0,0 +1,61 @@
var koa = require('koa');
var parse = require('co-body');
var session = require('koa-session');

var form = '<form action="/login" method="POST">\
<input name="username" type="text" value="username">\
<input name="password" type="password" placeholder="Le mot de passe est \'password\'">\
<button type="submit">Connexion</button>\
</form>';

var app = koa();

// Utilisez koa-session quelque part au début de la pile.
// Nous avons besoin de définir les `.keys` pour les cookies signés
app.keys = ['secret1', 'secret2', 'secret3'];
app.use(session(app));

/**
* Si `this.session.authenticated` existe, la personne voit « Bonjour tout le monde ».
* Dans le cas contraire, elle reçoit une erreur 401, faute d’authentification.
*/
app.use(function* home(next) {
if (this.request.path !== '/') return yield next;

if (this.session.authenticated) return this.body = 'Bonjour tout le monde';

this.status = 401;
});

/**
* Si la connexion réussit, la personne est authentifiée et redirigée sur `/`.
* Conseil : utilisez `this.redirect(…)`.
*/
app.use(function* login(next) {
if (this.request.path !== '/login') return yield next;

if (this.request.method === 'GET') return this.body = form;

if (this.request.method !== 'POST') return;

var body = yield parse(this);
if (body.username !== 'username'
|| body.password !== 'password') return this.status = 400;

this.session.authenticated = true;
this.redirect('/');
});

/**
* Redirigez sur `/login` quoi qu’il arrive.
* Si une personne va sur `/logout` alors qu’elle est déjà déconnectée, on va
* considérer que ce n’est pas une erreur.
*/
app.use(function* logout(next) {
if (this.request.path !== '/logout') return yield next;

this.session.authenticated = false;
this.redirect('/login');
});

app.listen(process.argv[2]);
6 changes: 6 additions & 0 deletions exercises/authentication/solution_fr/solution.txt
@@ -0,0 +1,6 @@
GET / : la personne non authentifiée reçoit une erreur 401
POST /login : erreur 400 quand username ou password est incorrect
POST /login : connexion réussie
GET / : Bonjour tout le monde
GET /logout : la personne est redirigée vers `/login`
GET / : la personne déconnectée reçoit une erreur 401