Compare commits
146 commits
ohnoyoutri
...
master
Author | SHA1 | Date | |
---|---|---|---|
05750ec31a | |||
a7431e4250 | |||
ef180b615c | |||
997d906331 | |||
2a2a6be194 | |||
971b390758 | |||
b9cff4e461 | |||
6aeca3fc26 | |||
|
a79a8d77ba | ||
|
5f95e0a4cd | ||
|
a39fbeb826 | ||
|
b03f1642f0 | ||
b850592ede | |||
d8745e4e07 | |||
|
add3ac8ebd | ||
|
09cf8410f0 | ||
932d035cd8 | |||
|
fc86c8092d | ||
|
c6ca4bf4c6 | ||
|
26c0a7b372 | ||
|
a9161ddea9 | ||
|
543e5345e1 | ||
|
2aa03b8582 | ||
|
38d3519a86 | ||
3c902a9516 | |||
2c98addf50 | |||
2620256da9 | |||
b5bf2a347b | |||
f933456c22 | |||
307a16d25d | |||
3b596472de | |||
|
e8ecae93fb | ||
|
f2c2bbaae9 | ||
2d15d097bd | |||
3274a65eb9 | |||
9027022d4d | |||
71c245774d | |||
|
67cd8f7fe1 | ||
|
aac90540f5 | ||
6c7d0801c2 | |||
e64ba35d3a | |||
956b570f67 | |||
|
00b419ef8f | ||
|
2cc2c3abb0 | ||
1777e5abdc | |||
|
aafe149fe3 | ||
cdb63e5508 | |||
|
0d76017e47 | ||
|
fdba8ab26f | ||
|
609f0ec9d0 | ||
|
625c4a8bb3 | ||
|
6e384b472b | ||
d017e30cc5 | |||
71228d0fcf | |||
bcbe73bac2 | |||
|
4cae1a7325 | ||
|
b18d476c8c | ||
a6b6fdcd50 | |||
1b4692e701 | |||
f3b715da48 | |||
df92dd65ba | |||
72a9b4f533 | |||
0743d9de40 | |||
f87b5076d0 | |||
e3f4b5e9cf | |||
4dd1827ee7 | |||
622b5624d0 | |||
9dc2c1a7ed | |||
bcd5da4adb | |||
2ac563f77a | |||
757b3a4c22 | |||
2f08f5b323 | |||
baf4e39b6a | |||
68ffd6188e | |||
40fd5b1e60 | |||
edfb7e80bf | |||
3c6e2e3780 | |||
69e7960233 | |||
b05d6dc3c0 | |||
|
a19233a610 | ||
|
40adbe15fd | ||
|
68b2fb3464 | ||
|
7e97165435 | ||
|
fd1fb9736a | ||
|
350bec7cfe | ||
62e031e63a | |||
7bd3aa4bb0 | |||
|
3d7dde29dc | ||
c960f961ce | |||
3d12c9e573 | |||
9b12b070ef | |||
de6a12a912 | |||
62acb5cdc7 | |||
69945cdb14 | |||
d38ce339b5 | |||
c9f4d0f605 | |||
b5244c8fa6 | |||
655d44e918 | |||
311c25f2c9 | |||
cf68b137da | |||
eec9d39a4a | |||
944efbd6fc | |||
a098c71b7b | |||
3d06efd8e3 | |||
3dd6a09845 | |||
44ddf8e7cf | |||
fcd2eb8eae | |||
0143bb0050 | |||
542d88437d | |||
12a549f7f2 | |||
5cacbb003f | |||
3fbff1b78e | |||
2e0487f67e | |||
6447a35715 | |||
f389f14bf8 | |||
4598a026ee | |||
899a03c76b | |||
3951f5875a | |||
b78c63f630 | |||
1cf6eefbc1 | |||
2dfc547957 | |||
08da575cd3 | |||
b5d63c7adc | |||
c82a00e35b | |||
702e4156e5 | |||
ae6bbb07f3 | |||
46d2ad6dc5 | |||
875a43e677 | |||
5a46e2576d | |||
5ddb074394 | |||
ff636bc355 | |||
ae1f8029d8 | |||
1e6c1adc38 | |||
2636d30743 | |||
c58cf255d3 | |||
b58b20d9be | |||
54c58ab6ea | |||
e8cca14021 | |||
9bd674db95 | |||
bd852937a6 | |||
6e53a1e40a | |||
d416e62d65 | |||
1829515873 | |||
fb9b4757e1 | |||
12e1af1339 | |||
4d28d4fec1 |
9 changed files with 1463 additions and 115 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
|||
# Directories and files
|
||||
node_modules/
|
||||
static/images/
|
||||
package-lock.json
|
||||
prankdata.txt
|
||||
activitydata.txt
|
||||
|
|
268
index.js
268
index.js
|
@ -1,41 +1,34 @@
|
|||
const fastify = require('fastify')({ logger: true })
|
||||
const fs = require('fs');
|
||||
const path = require('path')
|
||||
var LdapAuth = require('ldapauth-fork');
|
||||
const CryptoJS = require("crypto-js");
|
||||
// var LdapAuth = require('ldapauth-fork');
|
||||
|
||||
var usersBdd = "usersBdd.txt";
|
||||
var prankPath = "prankdata.txt";
|
||||
var activityPath = "activitydata.txt";
|
||||
var treasurePath = "treasuredata.txt";
|
||||
var goldenUsersPath = "goldenusers.txt";
|
||||
var servicePath = "servicestate.txt";
|
||||
|
||||
initFs();
|
||||
|
||||
let UsersBDD = JSON.parse(fs.readFileSync(usersBdd));
|
||||
|
||||
let PrankData = JSON.parse(fs.readFileSync(prankPath));
|
||||
let ActivityData = JSON.parse(fs.readFileSync(activityPath));
|
||||
let TreasureData = JSON.parse(fs.readFileSync(treasurePath));
|
||||
let GoldenUsers = JSON.parse(fs.readFileSync(goldenUsersPath));
|
||||
let AdminUsersUid = ["asyncnomi", "johan", "enthalpine", "fas", "arina", "billy", "remi", "pierre", "matmaz", "", "", ""];
|
||||
let ServiceState = JSON.parse(fs.readFileSync(servicePath));
|
||||
let AdminUsersUid = ["asyncnomi", "johan", "enthalpine", "fleur", "arina", "billy", "remi", "pierre", "matmaz", "mariusdrgc", "agathe", "jsansa"];
|
||||
let UsersToken = {};
|
||||
let TokenDurationSecond = 3600;
|
||||
let TokenDurationSecond = 360000;
|
||||
let MaxAmountCrepe = 10;
|
||||
let Supplements = ["nature", "sucre", "nutella", "confiture"];
|
||||
|
||||
var ldapConf = JSON.parse(fs.readFileSync("ldap-conf.json"));
|
||||
var LDAP = new LdapAuth({
|
||||
url: 'ldap://10.5.0.44',
|
||||
bindDN: 'cn='+ ldapConf.bindUser +',ou=service-users,dc=ldap,dc=rezo-rm,dc=fr',
|
||||
bindCredentials: ldapConf.bindPassword,
|
||||
searchBase: 'dc=ldap,dc=rezo-rm,dc=fr',
|
||||
searchFilter: '(uid={{username}})',
|
||||
reconnect: true,
|
||||
});
|
||||
LDAP.on('error', function (err) {
|
||||
console.error('LdapAuth: ', err);
|
||||
});
|
||||
ldapConf = null;
|
||||
|
||||
fastify.addContentTypeParser('application/json', {
|
||||
parseAs: 'string'
|
||||
parseAs: 'string',
|
||||
bodyLimit: 10485760
|
||||
}, function(req, body, done) {
|
||||
try {
|
||||
var json = JSON.parse(body)
|
||||
|
@ -51,28 +44,39 @@ fastify.register(require('@fastify/static'), {
|
|||
decorateReply: false
|
||||
})
|
||||
|
||||
fastify.get('/', async (request, reply) => {
|
||||
reply.redirect('/index.html')
|
||||
})
|
||||
|
||||
fastify.post('/login', async (request, reply) => {
|
||||
let content = request.body;
|
||||
if (content.hasOwnProperty("user")
|
||||
&& content.hasOwnProperty("password")) {
|
||||
let res = await authenticate(content.user, content.password);
|
||||
if (res.authState) {
|
||||
let now = new Date();
|
||||
UsersToken[res.authUser.uid] = {
|
||||
token: makeid(64),
|
||||
expire: now.setSeconds(now.getSeconds() + TokenDurationSecond)
|
||||
if (UsersBDD.hasOwnProperty(content.user)) {
|
||||
var hash;
|
||||
try {
|
||||
hash = CryptoJS.SHA512(content.password).toString();
|
||||
} catch {
|
||||
return {
|
||||
success: false,
|
||||
why: "Wrong username or password"
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
user: {
|
||||
uid: res.authUser.uid,
|
||||
givenName: res.authUser.givenName
|
||||
},
|
||||
token: UsersToken[res.authUser.uid].token
|
||||
if (hash === UsersBDD[content.user].password) {
|
||||
let now = new Date();
|
||||
UsersToken[content.user] = {
|
||||
token: makeid(64),
|
||||
expire: now.setSeconds(now.getSeconds() + TokenDurationSecond)
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
user: {
|
||||
uid: content.user,
|
||||
isAdmin: AdminUsersUid.includes(content.user)
|
||||
},
|
||||
token: UsersToken[content.user].token
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
why: "Wrong username or password"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
@ -88,10 +92,88 @@ fastify.post('/login', async (request, reply) => {
|
|||
}
|
||||
})
|
||||
|
||||
fastify.post('/register', async (request, reply) => {
|
||||
let content = request.body;
|
||||
if (content.hasOwnProperty("user")
|
||||
&& content.hasOwnProperty("password")) {
|
||||
if (UsersBDD.hasOwnProperty(content.user)) {
|
||||
return {
|
||||
success: false,
|
||||
why: "This user already exists"
|
||||
}
|
||||
} else {
|
||||
var hash;
|
||||
try {
|
||||
hash = CryptoJS.SHA512(content.password).toString();
|
||||
} catch {
|
||||
return {
|
||||
success: false,
|
||||
why: "What are you doing bruh ??"
|
||||
}
|
||||
}
|
||||
UsersBDD[content.user] = {
|
||||
password: hash
|
||||
}
|
||||
saveData(usersBdd, UsersBDD);
|
||||
let now = new Date();
|
||||
UsersToken[content.user] = {
|
||||
token: makeid(64),
|
||||
expire: now.setSeconds(now.getSeconds() + TokenDurationSecond)
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
user: {
|
||||
uid: content.user,
|
||||
isAdmin: AdminUsersUid.includes(content.user)
|
||||
},
|
||||
token: UsersToken[content.user].token
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
why: "The username or password is missing"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fastify.post('/switchState', async (request, reply) => {
|
||||
let content = request.body;
|
||||
let auth = checkAuthetification(content);
|
||||
if (auth.success) {
|
||||
if (AdminUsersUid.includes(content.uid)) {
|
||||
if (ServiceState.state == "closed") {
|
||||
ServiceState.state = "open";
|
||||
} else {
|
||||
ServiceState.state = "closed";
|
||||
}
|
||||
saveData(servicePath, ServiceState);
|
||||
return {
|
||||
success: true,
|
||||
state: ServiceState.state
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
why: "Not allowed"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return auth
|
||||
}
|
||||
})
|
||||
|
||||
fastify.post('/addPrank', async (request, reply) => {
|
||||
let content = request.body;
|
||||
let auth = checkAuthetification(content);
|
||||
if (auth.success) {
|
||||
if (ServiceState.state == "closed"
|
||||
&& !AdminUsersUid.includes(content.uid)) {
|
||||
return {
|
||||
success: false,
|
||||
why: "The service is for now, closed"
|
||||
}
|
||||
}
|
||||
if ("type" in content) {
|
||||
let prankUid = makeid(16);
|
||||
if ("prankUid" in content) {
|
||||
|
@ -117,10 +199,11 @@ fastify.post('/addPrank', async (request, reply) => {
|
|||
&& "supplement" in content) {
|
||||
let amount = parseInt(content.amount)
|
||||
if (!isNaN(amount)) {
|
||||
if (!Supplements.contains(content.supplement)) {
|
||||
if (Supplements.includes(content.supplement)) {
|
||||
if (amount < MaxAmountCrepe) {
|
||||
let prankUid = makeid(16);
|
||||
PrankData[prankUid] = {
|
||||
date: new Date(),
|
||||
creator: content.uid,
|
||||
type: content.type,
|
||||
where: content.where,
|
||||
|
@ -132,7 +215,7 @@ fastify.post('/addPrank', async (request, reply) => {
|
|||
}
|
||||
saveData(prankPath, PrankData);
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
uid: prankUid,
|
||||
prank: PrankData[prankUid]
|
||||
}
|
||||
|
@ -176,7 +259,7 @@ fastify.post('/addPrank', async (request, reply) => {
|
|||
}
|
||||
saveData(prankPath, PrankData);
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
uid: prankUid,
|
||||
prank: PrankData[prankUid]
|
||||
}
|
||||
|
@ -291,7 +374,7 @@ fastify.post('/get', async (request, reply) => {
|
|||
case "prank":
|
||||
if (AdminUsersUid.includes(content.uid)) {
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
prankData: PrankData
|
||||
}
|
||||
} else {
|
||||
|
@ -309,27 +392,37 @@ fastify.post('/get', async (request, reply) => {
|
|||
break;
|
||||
case "activity":
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
activityData: ActivityData
|
||||
}
|
||||
break;
|
||||
case "treasure":
|
||||
let treasureData = JSON.parse(JSON.stringify(TreasureData));
|
||||
for (treasure in treasureData) {
|
||||
treasureData[treasure].activity = ActivityData[treasureData[treasure].activityUid];
|
||||
}
|
||||
if (AdminUsersUid.includes(content.uid)) {
|
||||
return {
|
||||
sucess: true,
|
||||
prankData: TreasureData
|
||||
}
|
||||
} else {
|
||||
let treasureData = {};
|
||||
for (treasure in TreasureData) {
|
||||
if (TreasureData[treasure].creator == content.uid) {
|
||||
treasureData[treasure] = TreasureData[treasure];
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
treasureData: treasureData
|
||||
}
|
||||
} else {
|
||||
let treasureDataUser = {};
|
||||
for (treasure in treasureData) {
|
||||
if (treasureData[treasure].creator == content.uid) {
|
||||
treasureDataUser[treasure] = treasureData[treasure];
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
treasureData: treasureDataUser
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "state":
|
||||
return {
|
||||
success: true,
|
||||
state: ServiceState.state
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -344,6 +437,18 @@ fastify.post('/get', async (request, reply) => {
|
|||
why: "Missing type"
|
||||
}
|
||||
}
|
||||
} else if ("type" in content) {
|
||||
switch (content.type) {
|
||||
case "activity":
|
||||
return {
|
||||
success: true,
|
||||
activityData: ActivityData
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return auth;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return auth
|
||||
}
|
||||
|
@ -381,7 +486,7 @@ fastify.post('/addActivity', async (request, reply) => {
|
|||
}
|
||||
saveData(activityPath, ActivityData);
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
uid: activityUid,
|
||||
activity: ActivityData[activityUid]
|
||||
}
|
||||
|
@ -403,7 +508,7 @@ fastify.post('/addActivity', async (request, reply) => {
|
|||
}
|
||||
saveData(activityPath, ActivityData);
|
||||
return {
|
||||
sucess: true,
|
||||
success: true,
|
||||
uid: activityUid,
|
||||
activity: ActivityData[activityUid]
|
||||
}
|
||||
|
@ -454,16 +559,16 @@ fastify.post('/sendTreasure', async (request, reply) => {
|
|||
&& "activityUid" in content) {
|
||||
let treasureUid = makeid(16);
|
||||
if ("treasureUid" in content) {
|
||||
let treasureExists = check(content, "activityUid", ActivityData)
|
||||
let treasureExists = check(content, "treasureUid", TreasureData)
|
||||
if (treasureExists.success) {
|
||||
if (treasureData[treasureUid].state != "Pending"
|
||||
&& treasureData[treasureUid].creator == content.uid) {
|
||||
if (TreasureData[content.treasureUid].state != "Pending"
|
||||
|| TreasureData[content.treasureUid].creator != content.uid) {
|
||||
return {
|
||||
success: false,
|
||||
why: "You cannot edit already accepted or refused treasure request, or request form other people"
|
||||
}
|
||||
} else {
|
||||
treasureUid = content.prankUid;
|
||||
treasureUid = content.treasureUid;
|
||||
}
|
||||
} else {
|
||||
return treasureExists;
|
||||
|
@ -473,15 +578,29 @@ fastify.post('/sendTreasure', async (request, reply) => {
|
|||
if (activityExists.success) {
|
||||
if (ActivityData[content.activityUid].type == "treasure") {
|
||||
let imageUid = makeid(128);
|
||||
fs.writeFileSync("static/images/"+imageUid, content.image);
|
||||
let fileImage = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<img style='object-fit: contain; width:100%; height:100%;' src='${content.image}'/>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
fs.writeFileSync("static/images/" + imageUid + ".html", fileImage);
|
||||
TreasureData[treasureUid] = {
|
||||
date: new Date(),
|
||||
creator: content.uid,
|
||||
image: imageUid,
|
||||
desc: content.desc,
|
||||
activity: content.activityUid,
|
||||
activityUid: content.activityUid,
|
||||
state: "Pending"
|
||||
}
|
||||
saveData(treasurePath, TreasureData);
|
||||
return {
|
||||
success: true,
|
||||
uid: treasureUid,
|
||||
treasure: TreasureData[treasureUid]
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
|
@ -538,7 +657,7 @@ fastify.post('/acceptTreasure', async (request, reply) => {
|
|||
if (treasureExists.success) {
|
||||
TreasureData[content.treasureUid].state = "Accepted";
|
||||
saveData(treasurePath, TreasureData);
|
||||
ActivityData[GoldenUsers[activityUid].activityUid].treasureState = "Accepted";
|
||||
ActivityData[TreasureData[content.treasureUid].activityUid].treasureState = "Accepted";
|
||||
saveData(activityPath, ActivityData);
|
||||
GoldenUsers[TreasureData[content.treasureUid].activityUid] = {
|
||||
userUid: TreasureData[content.treasureUid].creator,
|
||||
|
@ -581,7 +700,7 @@ fastify.post('/isGolden', async (request, reply) => {
|
|||
}
|
||||
}
|
||||
return {
|
||||
sucess: false
|
||||
success: false
|
||||
}
|
||||
} else {
|
||||
return auth
|
||||
|
@ -592,24 +711,6 @@ function saveData(path, data) {
|
|||
fs.writeFileSync(path, JSON.stringify(data));
|
||||
}
|
||||
|
||||
function authenticate(user, pwd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
LDAP.authenticate(user, pwd, function(err, user) {
|
||||
if (user && err == null) {
|
||||
resolve({
|
||||
authState: true,
|
||||
authUser: user
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
authState: false,
|
||||
authUser: null
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function checkAuthetification(content) {
|
||||
if (content.hasOwnProperty("uid")
|
||||
&& content.hasOwnProperty("token")) {
|
||||
|
@ -684,6 +785,9 @@ function checkManage(content, input, data) {
|
|||
}
|
||||
|
||||
function initFs() {
|
||||
if (!fs.existsSync(usersBdd)) {
|
||||
fs.writeFileSync(usersBdd, "{}");
|
||||
}
|
||||
if (!fs.existsSync(prankPath)) {
|
||||
fs.writeFileSync(prankPath, "{}");
|
||||
}
|
||||
|
@ -696,6 +800,12 @@ function initFs() {
|
|||
if (!fs.existsSync(goldenUsersPath)) {
|
||||
fs.writeFileSync(goldenUsersPath, "{}");
|
||||
}
|
||||
if (!fs.existsSync(servicePath)) {
|
||||
fs.writeFileSync(servicePath, JSON.stringify({state: 'closed'}));
|
||||
}
|
||||
if (!fs.existsSync("static/images")){
|
||||
fs.mkdirSync("static/images");
|
||||
}
|
||||
}
|
||||
|
||||
function makeid(length) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@fastify/static": "^6.6.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"fastify": "^4.10.2",
|
||||
"ldapauth-fork": "^5.0.5",
|
||||
"password-prompt": "^1.1.2"
|
||||
|
|
|
@ -73,8 +73,8 @@ a:hover {
|
|||
background: url("../img/background-letter.jpg");
|
||||
background-size: cover;
|
||||
background-position: right;
|
||||
|
||||
transition: 1.5s transform 0s ease-out;
|
||||
overflow: scroll;
|
||||
transition: 1s transform 0s ease-out;
|
||||
}
|
||||
|
||||
#logo {
|
||||
|
@ -92,7 +92,7 @@ a:hover {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#spacer {
|
||||
.spacer {
|
||||
padding: 1px;
|
||||
margin: 30px 0 30px 0;
|
||||
background-color: #00000054;
|
||||
|
@ -134,8 +134,6 @@ a:hover {
|
|||
}
|
||||
|
||||
#login-form {
|
||||
margin-top: 25vh;
|
||||
margin-bottom: 10vh;
|
||||
padding: 0px;
|
||||
width: 50vw;
|
||||
}
|
||||
|
@ -149,7 +147,7 @@ a:hover {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.login-form-control {
|
||||
.form-control {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-bottom: 1px solid #d75b00;
|
||||
|
@ -158,7 +156,7 @@ a:hover {
|
|||
padding: 5px;
|
||||
}
|
||||
|
||||
.login-form-control:focus {
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-bottom: 2px solid #923e01;
|
||||
}
|
||||
|
@ -182,6 +180,144 @@ button[type="submit"]:hover {
|
|||
color: #ffffff;
|
||||
}
|
||||
|
||||
.admin-textarea, .admin-input-date, #activityType {
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid orange;
|
||||
margin: 5px 0px;
|
||||
font-size: 15px;
|
||||
height: 27px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.activity, .prank, .treasure {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 30px 0;
|
||||
border-bottom: 2px solid grey;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.activity>*, .prank>*, .treasure>* {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.activity-btn, .prank-btn, .treasure-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.activity-btn>*, .prank-btn>*, .treasure-btn>* {
|
||||
margin-left: auto;
|
||||
border: 1px solid orange;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: #fa45;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.activity-btn>*:hover, .prank-btn>*:hover, .treasure-btn>*:hover {
|
||||
background-color: #faa5;
|
||||
}
|
||||
|
||||
#admin-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 3px solid black;
|
||||
height: 40px;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.admin-menu:hover {
|
||||
background-color: #00000036;
|
||||
}
|
||||
|
||||
.admin-menu:first-of-type {
|
||||
border-left: 3px solid black;
|
||||
}
|
||||
|
||||
.activity-uid, .prank-uid, .prank-date, .treasure-uid, .treasure-date, #activite-place {
|
||||
color: #00000078;
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.prank-date, .treasure-date {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.treasure-image>a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#error-message, #error-message-demande, #error-message-register {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.treasure {
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
|
||||
.treasure-submitted {
|
||||
background-color: rgba(67, 67, 67, 0.296);
|
||||
}
|
||||
|
||||
.treasure-accepted {
|
||||
background-color: rgba(0, 255, 0, 0.46);
|
||||
}
|
||||
|
||||
.treasure-refused {
|
||||
background-color: rgba(255, 0, 0, 0.397);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
z-index: 99;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
transition: opacity 500ms;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#treasure-popup {
|
||||
margin: 70px auto;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
width: calc(100% - 10vw);
|
||||
position: relative;
|
||||
transition: all 5s ease-in-out;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 30px;
|
||||
transition: all 200ms;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
.close:hover {
|
||||
color: #d75b00;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.bg-full {
|
||||
display: none;
|
||||
|
@ -189,6 +325,7 @@ button[type="submit"]:hover {
|
|||
.container {
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
border-radius: 0px;
|
||||
box-shadow: none;
|
||||
|
@ -200,7 +337,7 @@ button[type="submit"]:hover {
|
|||
#logo > img {
|
||||
width: 150px;
|
||||
}
|
||||
#spacer {
|
||||
.spacer {
|
||||
display: none;
|
||||
}
|
||||
.row-section {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 252 KiB |
|
@ -38,16 +38,18 @@
|
|||
</div>
|
||||
<div class="column-section">
|
||||
<h1>Prochaine activité</h1>
|
||||
<span id="timer">00:00:10</span>
|
||||
<p id="activite-desc">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Dicta tenetur tempora similique. A id esse expedita atque dolor eum itaque fugiat enim nisi dicta. Architecto mollitia quasi sed voluptatibus? Veniam.</p>
|
||||
<span id="timer">2 jours 00:00:10</span>
|
||||
<h2 id="activite-title"></h2>
|
||||
<p id="activite-desc"></p>
|
||||
<p id="activite-place"></p>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row-section">
|
||||
<div class="column-section">
|
||||
<h1>Planning des activité</h1>
|
||||
<h1>Planning des activités</h1>
|
||||
<img src="img/schedule.png" id="schedule" alt="Planning des activité" srcset="">
|
||||
</div>
|
||||
<div id="spacer" class="column-section"></div>
|
||||
<div class="sapcer column-section"></div>
|
||||
<div class="column-section">
|
||||
<h1>Ordre de mission</h1>
|
||||
<a id="prank-button">
|
||||
|
@ -56,8 +58,7 @@
|
|||
</a>
|
||||
<p id="prank-desc">
|
||||
OSS 110'Metz est une organisation remplie d'espions qualifiés pour remplir presque toutes tes demandes !
|
||||
Cliquez sur le bouton ci-dessus puis suivez les instructions. Attention, un compte <a href="https://re2o.rezo-rm.fr/users/new_user" target="_blank">Rezo</a>
|
||||
est nécessaire afin de garantir l'identité des demandeurs !
|
||||
Cliquez sur le bouton ci-dessus puis suivez les instructions.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,7 +66,7 @@
|
|||
<div class="column-section">
|
||||
<h1>Chasse au trésor</h1>
|
||||
<p id="chasse-desc">
|
||||
Chaque jour de la semaine tes espions préférés ont préparé pour toi une <i style="font-weight: 900;">chasse au trésor</i> !
|
||||
Pendante toute la semaine tes espions préférés ont préparé pour toi une <i style="font-weight: 900;">chasse au trésor</i> !
|
||||
Résous les énigmes pour tenter de gagner le fameux <u>ticket d'or</u>. Il te permettra de t'abrever gratuitement pendants les évènements festifs !
|
||||
</p>
|
||||
</div>
|
||||
|
@ -79,39 +80,139 @@
|
|||
</footer>
|
||||
</div>
|
||||
|
||||
<div id="admin-page" style="display: none">
|
||||
<div id="admin-page" class="container" style="display: none">
|
||||
<div id="admin-header">
|
||||
<div id="admin-prank" class="admin-menu">Prank</div>
|
||||
<div id="admin-treasure" class="admin-menu">Trésors</div>
|
||||
<div id="admin-activity" class="admin-menu">Activités</div>
|
||||
</div>
|
||||
<div id="admin-content">
|
||||
|
||||
</div>
|
||||
</div> <!-- end admin page -->
|
||||
|
||||
<div class="container" id="login-page" style="display: none;">
|
||||
<p>Connection</p>
|
||||
<div class="column-section">
|
||||
<div id="login-form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="login-form-control" placeholder="Nom d'espion" name="login" id="login"/>
|
||||
<input type="text" class="form-control" placeholder="Nom d'espion" name="login" id="login"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="login-form-control" placeholder="Mot de passe secret" name="password" id="password" />
|
||||
<input type="password" class="form-control" placeholder="Mot de passe secret" name="password" id="password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="login-button">Se connecter</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p id="error-message"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Inscription</p>
|
||||
<div class="column-section">
|
||||
<div id="register-form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Nom d'espion" name="login" id="register-user"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" placeholder="Mot de passe secret" name="password" id="register-password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" placeholder="Confirmer le mot de passe secret" name="password" id="register-password-confirm" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="register-button">S'inscrire</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p id="error-message-register"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row banner">
|
||||
<h2>Notice de l'espion</h2>
|
||||
<h2>Notice pour l'espion</h2>
|
||||
<p id="notice-espion">
|
||||
Seul les espions reconnus par le Rézo pourrons se connecter pour jouer des tours à leurs camarrades.
|
||||
Si tu n'es pas encore un espion reconnu, tu peux le devenir <a href="https://re2o.rezo-rm.fr/users/new_user" target="_blank">ici</a>.
|
||||
Vous êtes espions et devez savoir retenir des mots de passe, car pour des raisons de sécurité celui-ci ne peut pas être changé. Alors faite attention !
|
||||
</p>
|
||||
</div>
|
||||
</div> <!-- end login page -->
|
||||
|
||||
<div id="demande-page" style="display: none">
|
||||
<div id="demande-page" class="container" style="display: none">
|
||||
<div class="column-section">
|
||||
<h1>Demandes</h1>
|
||||
<p>Ici vous pouvez demandez à un espion aguerri de vous livrer des crêpes. Aussi, vous pouvez tentez de valider la chasse au trésor du jour !
|
||||
Pour cela il suffit d'envoyer une photo du ticket avec l'endroit où vous l'avez trouvé.
|
||||
</p>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row-section">
|
||||
<div class="column-section" id="demande-form">
|
||||
<h2>Crêpes</h2>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Lieu de livraison" id="demande-where">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" placeholder="Quantité" max="9" id="demande-amount">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select class="form-control" id="demande-supp">
|
||||
<option value="nature">Nature</option>
|
||||
<option value="sucre">Sucre</option>
|
||||
<option value="nutella">Nutella</option>
|
||||
<option value="confiture">Confiture</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" placeholder="Notes" id="demande-notes" ></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="demande-button">Envoyer</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p id="error-message-demande"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
<div class="column-section">
|
||||
<h2>Chasse au trésor</h2>
|
||||
<p>Retrouve ici toutes les énigmes. Celles en vert sont déjà resolues alors dépéchez vous de résoudre les autres !</p>
|
||||
<div class="column-section" id="treasure-list">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
<div class="column-section">
|
||||
<h1>Vos demandes en cours</h1>
|
||||
<div class="column-section" id="demande-list"></div>
|
||||
</div>
|
||||
</div> <!-- end demande page -->
|
||||
</div>
|
||||
|
||||
<div class="overlay">
|
||||
<div id="treasure-popup">
|
||||
<div class="column-section">
|
||||
<h2>Soumettre la résolution d'une énigme !</h2>
|
||||
<a class="close" href="#">×</a>
|
||||
<p id="treasure-popup-title"></p>
|
||||
<input type="hidden" id="treasure-popup-uid">
|
||||
<input type="hidden" id="treasure-popup-activity-uid">
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="file" id="treasure-popup-image" >
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" id="treasure-popup-desc" placeholder="Ajouter une description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="treasure-popup-button">Envoyer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/typeit@8.7.0/dist/index.umd.js"></script>
|
||||
<script src="js/main.js" defer></script>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var $animation_elements = $("#prank-desc, #activite-desc, #chasse-desc, #notice-espion");
|
||||
var $animation_elements = $("#prank-desc, #chasse-desc, #notice-espion");
|
||||
var $window = $(window)
|
||||
|
||||
function check_if_in_view() {
|
||||
|
@ -18,7 +18,7 @@ function check_if_in_view() {
|
|||
if(!$element.hasClass('animated')) {
|
||||
$element.addClass('animated');
|
||||
var a = new TypeIt('#' + $element.attr('id'), {
|
||||
speed: 30,
|
||||
speed: 50,
|
||||
lifeLike: true,
|
||||
})
|
||||
.go();
|
||||
|
|
File diff suppressed because it is too large
Load diff
29
stats.js
Normal file
29
stats.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
const fs = require('fs');
|
||||
let PrankData = JSON.parse(fs.readFileSync("prankdata.txt"));
|
||||
|
||||
let nbPrank = 0;
|
||||
let nbCrepe = 0;
|
||||
let meanCrepe = 0;
|
||||
let userPrank = {};
|
||||
|
||||
for (var uid in PrankData) {
|
||||
if (PrankData[uid].type == "crêpe") {
|
||||
if (PrankData[uid].state == "Done") {
|
||||
nbPrank ++;
|
||||
nbCrepe += parseInt(PrankData[uid].amount)
|
||||
if (!userPrank[PrankData[uid].creator]) {
|
||||
userPrank[PrankData[uid].creator] = 0;
|
||||
}
|
||||
userPrank[PrankData[uid].creator] += parseInt(PrankData[uid].amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meanCrepe = nbCrepe / nbPrank;
|
||||
|
||||
console.log("Nombre de mission mission achevé: " + nbPrank)
|
||||
console.log("Nombre de crêpe servis: " + nbCrepe)
|
||||
console.log("Nombre moyen de crêpe par demande: " + meanCrepe + "\n")
|
||||
for (var user in userPrank) {
|
||||
console.log(user + " a commandé " + userPrank[user] + " crêpe")
|
||||
}
|
Loading…
Reference in a new issue