Commit 344319f5 authored by Rosanny Sihombing's avatar Rosanny Sihombing
Browse files

functionality updates

parent a2d207dc
const Project = require("./project"); const Project = require("./project");
class Repo extends Project { class Repo extends Project {
constructor(ownerGitlabId, id, name, desc, logo) { constructor(ownerGitlabId, id, name, desc, logo, path) {
super(ownerGitlabId, id, name, desc, logo) super(ownerGitlabId, id, name, desc, logo, path)
} }
} }
......
const Project = require("./project"); const Project = require("./project");
class Website extends Project { class Website extends Project {
constructor(ownerGitlabId, id, name, desc, logo, path, settingUrl, kontaktUrl, isPublished) { constructor(ownerGitlabId, id, name, desc, logo, path) {
super(ownerGitlabId, id, name, desc, logo, path) super(ownerGitlabId, id, name, desc, logo, path)
this.settingUrl = settingUrl
this.kontaktUrl = kontaktUrl
this.isPublished = isPublished
}
// getter
getSettingUrl() {
return this.settingUrl
}
getKontaktUrl() {
return this.kontaktUrl
}
getIsPublished() {
return this.isPublished
}
// setter
setSettingUrl(newSettingUrl) {
this.settingUrl = newSettingUrl
}
setKontaktUrl(newKontaktUrl) {
this.kontaktUrl = newKontaktUrl
} }
} }
......
...@@ -5,67 +5,52 @@ const fs = require('fs') ...@@ -5,67 +5,52 @@ const fs = require('fs')
var formData = require('form-data') var formData = require('form-data')
var gitlab = { var gitlab = {
getUserIdByEmail: function(email, callback) { // todo: GraphQL currentUser
let dataConfig = {
getUserByEmail: async function(email) {
return axios({
method: 'get', method: 'get',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/users?search='+email, url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/users?search='+email,
headers: { headers: {
'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects} 'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects}
}
axios(dataConfig)
.then(function (response) {
let res = {
error: false,
data: response.data[0].id}
callback(res)
}) })
.catch(function (err) { .then(res => userData = {
let res = { id: res.data[0].id,
error: true, username: res.data[0].username
data: err}
callback(res)
}) })
.catch(err => console.error(err))
}, },
createNewPages: function(newPagesData, newLogoFile, callback) { createNewPages: async function(newPagesData, newLogoFile, template) {
let data = new formData() let data = new formData()
data.append('avatar', fs.createReadStream(newLogoFile)) data.append('avatar', fs.createReadStream(newLogoFile))
let dataConfig = { return axios({
method: 'post', method: 'post',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/user/'+newPagesData.getOwnerGitlabId()+ url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/user/'+newPagesData.getOwnerGitlabId()+
'?name='+newPagesData.getName()+'&description='+newPagesData.getDesc()+'&tag_list=website'+ '?name='+newPagesData.getName()+'&description='+newPagesData.getDesc()+'&tag_list=website'+
'&use_custom_template=true&template_name=page_basic', '&use_custom_template=true&template_name='+template,
headers: { headers: {
'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects, 'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects,
...data.getHeaders() ...data.getHeaders()
}, },
data : data data: data
}
axios(dataConfig)
.then(response => {
let res = {
error: false,
data: response.data}
callback(res)
}) })
.catch(err => { .then(res => res = {
console.log(err) error: false,
let res = { data: res.data
error: true, })
data: err.response.data} .catch(err => res = {
callback(res) error: true,
data: err.response.data
}) })
}, },
updateProject: function(updatedProjectData, newLogoFile, callback){ updateProject: async function(updatedProjectData, newLogoFile){
console.log(updatedProjectData)
let data = new formData() let data = new formData()
if (newLogoFile) { if (newLogoFile) {
data.append('avatar', fs.createReadStream(newLogoFile)) data.append('avatar', fs.createReadStream(newLogoFile))
} }
let dataConfig = { return axios({
method: 'put', method: 'put',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+updatedProjectData.getId()+ url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+updatedProjectData.getId()+
'?name='+updatedProjectData.getName()+'&description='+updatedProjectData.getDesc(), '?name='+updatedProjectData.getName()+'&description='+updatedProjectData.getDesc(),
...@@ -74,68 +59,70 @@ var gitlab = { ...@@ -74,68 +59,70 @@ var gitlab = {
...data.getHeaders() ...data.getHeaders()
}, },
data : data data : data
}
axios(dataConfig)
.then(response => {
let res = {
error: false,
data: response.data}
callback(res)
}) })
.catch(err => { .then(res => res = {
console.log(err) error: false,
let res = { data: res.data
error: true, })
data: err.response.data} .catch(err => res = {
callback(res) error: true,
data: err.response.data
})
},
getUserProjects: async function(gitlabUserId) {
return axios({
method: 'get',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/users/'+gitlabUserId+'/projects?private_token='+
config.gitlab.token_readWriteProjects+'&owned=true&simple=true&visibility=public'
}) })
.then(res => res.data)
.catch(err => console.error(err))
}, },
getUserProjects: function(gitlabUserId, callback) { getProjectById: async function(projectId) {
axios.get('https://transfer.hft-stuttgart.de/gitlab/api/v4/users/'+gitlabUserId+'/projects?private_token='+ return axios({
config.gitlab.token_readWriteProjects+'&owned=true&simple=true&visibility=public') method: 'get',
.then(response => { url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+projectId+'?private_token='+
let res = { config.gitlab.token_readWriteProjects
error: false,
data: response.data}
callback(res)
}) })
.catch(err => { .then(res => res.data)
let res = { .catch(err => console.error(err))
error: true, },
data: err.message} getProjectPipelineLatestStatus: async function(projectId) {
callback(res) return axios({
method: 'get',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+projectId+'/pipelines'
}) })
.then(res => res.data[0].status)
.catch(err => console.error(err))
}, },
getProjectIdsFromRunners: function(gitlabUserId, callback) { // delete peoject: https://docs.gitlab.com/ee/api/projects.html#delete-project
let projectIds = [] //
let dataConfig = { // test GraphQL
getGraphqlTest: function(callback) {
axios({
url: 'https://gitlab.com/api/graphql',
method: 'get', method: 'get',
url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/runners/7', headers: {
headers: { 'Content-Type': 'application/json',
'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects} 'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects
} },
data: {
axios(dataConfig) query: `{
.then(function (response) { currentUser {
let projects = response.data.projects id
projects.forEach((project) => { username
if(project.namespace.id == gitlabUserId) { }
projectIds.push(project.id) }`
/* query: `{
projects {
nodes {
id
}
} }
}) }` */
let res = { }
error: false, }).then((result) => {
data: projectIds} console.log(JSON.stringify(result.data))
callback(res)
})
.catch(function (err) {
let res = {
error: true,
data: err}
callback(res)
}); });
} }
} }
......
...@@ -13,6 +13,7 @@ const crypto = require('crypto') ...@@ -13,6 +13,7 @@ const crypto = require('crypto')
const mailer = require('./mailer') const mailer = require('./mailer')
const logoDir = 'public/upload/' const logoDir = 'public/upload/'
const tpGitlabURL = 'https://transfer.hft-stuttgart.de/gitlab/' const tpGitlabURL = 'https://transfer.hft-stuttgart.de/gitlab/'
const tpGitlabPagesURL = 'https://transfer.hft-stuttgart.de/pages/'
const portalUser = require('../classes/user') const portalUser = require('../classes/user')
const projectInformation = require('../classes/website') const projectInformation = require('../classes/website')
...@@ -128,7 +129,6 @@ module.exports = function (app, config, passport, i18n) { ...@@ -128,7 +129,6 @@ module.exports = function (app, config, passport, i18n) {
} }
}) })
} }
res.render(lang+'/account/home', { res.render(lang+'/account/home', {
user: loggedInUser user: loggedInUser
}); });
...@@ -180,7 +180,7 @@ module.exports = function (app, config, passport, i18n) { ...@@ -180,7 +180,7 @@ module.exports = function (app, config, passport, i18n) {
} }
}) })
app.get('/services', function(req, res){ app.get('/services', async function(req, res){
if(!req.isAuthenticated() && !loggedInUser) { if(!req.isAuthenticated() && !loggedInUser) {
res.redirect('/login') res.redirect('/login')
} else { } else {
...@@ -189,65 +189,45 @@ module.exports = function (app, config, passport, i18n) { ...@@ -189,65 +189,45 @@ module.exports = function (app, config, passport, i18n) {
} else { } else {
let gitlabReposArr = [] let gitlabReposArr = []
let gitlabPagesArr = [] let gitlabPagesArr = []
if(loggedInUser.getGitlabUserId()) { // for users who have activated their gitlab account if(loggedInUser.getGitlabUserId()) { // for users who have activated their gitlab account
async.waterfall([ let userProjects = await gitlab.getUserProjects(loggedInUser.getGitlabUserId())
// check projects in runners if (!userProjects)
function(callback) { res.status(500).send("something went wrong :/")
let gitlabRunnersProjectIdsArr
gitlab.getProjectIdsFromRunners(loggedInUser.getGitlabUserId(), function(data){ for (project in userProjects) {
if(data.error) if (userProjects[project].tag_list.includes('website')) {
return res.status(500).send(data.data) let page = {
gitlabRunnersProjectIdsArr = data.data projectInformation: new projectInformation(loggedInUser.getGitlabUserId(), userProjects[project].id, userProjects[project].name,
callback(null, gitlabRunnersProjectIdsArr) userProjects[project].description, userProjects[project].avatar_url, userProjects[project].path_with_namespace),
}) pipelineStatus: await gitlab.getProjectPipelineLatestStatus(userProjects[project].id)
}
], function(err, gitlabRunnersProjectIdsArr) {
// get user projects
gitlab.getUserProjects(loggedInUser.getGitlabUserId(), function(data){
if (data.error)
return res.status(500).send(data.data)
let gitlabData = data.data
for(let i = 0; i < gitlabData.length; i++){
if (gitlabData[i].tag_list.includes('website')) {
let idxRunners = gitlabRunnersProjectIdsArr.indexOf(gitlabData[i].id)
let isWebsitePublished = false
if (idxRunners > 0) {
isWebsitePublished = true
}
let page = new projectInformation(loggedInUser.getGitlabUserId(), gitlabData[i].id, gitlabData[i].name, gitlabData[i].description,
gitlabData[i].avatar_url, gitlabData[i].path, null, null, isWebsitePublished)
gitlabPagesArr.push(page)
} else {
let repo = new projectRepo(loggedInUser.getGitlabUserId(), gitlabData[i].id, gitlabData[i].name, gitlabData[i].description,
gitlabData[i].avatar_url, gitlabData[i].path)
gitlabReposArr.push(repo)
}
} }
gitlabPagesArr.push(page)
res.render(lang+'/account/services', { } else {
user: loggedInUser, let repo = new projectRepo(loggedInUser.getGitlabUserId(), userProjects[project].id, userProjects[project].name,
gitlabRepos: gitlabReposArr, userProjects[project].description, userProjects[project].avatar_url, userProjects[project].path_with_namespace)
gitlabPages: gitlabPagesArr gitlabReposArr.push(repo)
}) }
}) }
res.render(lang+'/account/services', {
user: loggedInUser,
gitlabRepos: gitlabReposArr,
gitlabPages: gitlabPagesArr
}) })
} else { // for users who have not activated their gitlab account yet } else { // for users who have not activated their gitlab account yet
gitlab.getUserIdByEmail(loggedInUser.getEmail(), function(data){ let gitlabUser = await gitlab.getUserByEmail(loggedInUser.getEmail())
if (data.error) { // RS: if error, then what?
res.status(500).render(lang+'/500', { error: data.data }) let gitlabActivationData = {
user_id: loggedInUser.getId(),
gitlab_userId: gitlabUser.id}
// RS: update to await
methods.addGitlabUser(gitlabActivationData, function(err){
if(err) {
res.status(500).render(lang+'/500', { error: err })
} else { } else {
let gitlabActivationData = { loggedInUser.setGitlabUserId(gitlabActivationData.gitlab_userId)
user_id: loggedInUser.getId(), res.redirect('/account/services')
gitlab_userId: data.data}
methods.addGitlabUser(gitlabActivationData, function(err){
if(err) {
res.status(500).render(lang+'/500', { error: err })
} else {
loggedInUser.setGitlabUserId(gitlabActivationData.gitlab_userId)
res.redirect('/account/services')
}
})
} }
}) })
} }
...@@ -480,13 +460,19 @@ module.exports = function (app, config, passport, i18n) { ...@@ -480,13 +460,19 @@ module.exports = function (app, config, passport, i18n) {
// ============= NEW GITLAB PAGES =========================== // ============= NEW GITLAB PAGES ===========================
app.get('/newInformation', function(req, res){ app.get('/newInformation', async function(req, res){
if (!req.isAuthenticated() && !loggedInUser) { if (!req.isAuthenticated() && !loggedInUser) {
res.redirect('/login') res.redirect('/login')
} else { } else {
res.render(lang+'/account/newInformation', { let gitlabUser = await gitlab.getUserByEmail(loggedInUser.getEmail())
user: loggedInUser if (!gitlabUser) { // no user found
}) res.redirect('/account/service')
} else {
res.render(lang+'/account/newInformation', {
user: loggedInUser,
gitlabUsername: gitlabUser.username
})
}
} }
}) })
app.post('/newInformation', function(req, res) { app.post('/newInformation', function(req, res) {
...@@ -499,7 +485,8 @@ module.exports = function (app, config, passport, i18n) { ...@@ -499,7 +485,8 @@ module.exports = function (app, config, passport, i18n) {
} else { } else {
let projectName = req.body.name.toLowerCase().replace(/\s/g, '-') let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
let projectDesc = req.body.description let projectDesc = req.body.description
let newInformation = new projectInformation(loggedInUser.getGitlabUserId(), null, projectName, projectDesc, null, null, null, null, false) let projectTemplate = req.body.template
let newInformation = new projectInformation(loggedInUser.getGitlabUserId(), null, projectName, projectDesc, null, null)
if (!req.files) { if (!req.files) {
res.flash('error', 'Bitte geben Sie ein Projektlogo an.') res.flash('error', 'Bitte geben Sie ein Projektlogo an.')
...@@ -513,28 +500,23 @@ module.exports = function (app, config, passport, i18n) { ...@@ -513,28 +500,23 @@ module.exports = function (app, config, passport, i18n) {
callback(err, newLogoFile) callback(err, newLogoFile)
}) })
}, },
function(newLogoFile, callback){ // create a new GitLab Page async function(newLogoFile){ // create a new GitLab Page
gitlab.createNewPages(newInformation, newLogoFile, function(data){ let newPages = await gitlab.createNewPages(newInformation, newLogoFile, projectTemplate)
let result = data.data if (newPages.error) {
if (data.error) { if(newPages.data.message.name == "has already been taken") {
if(result.message.name == "has already been taken") { res.flash("error", "Der Projektname '"+newInformation.getName()+"' ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
res.flash("error", "Der Projektname '"+newInformation.getName()+"' ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
} else {
res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
}
res.redirect('/account/newInformation')
} else { } else {
newInformation.setId(result.id) res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
newInformation.setLogo(result.avatar_url)
newInformation.setPath(result.path)
newInformation.setSettingUrl(tpGitlabURL+result.namespace.path+'/'+result.name+'/-/edit/master/public/settings.js')
newInformation.setKontaktUrl(tpGitlabURL+result.namespace.path+'/'+result.name+'/-/edit/master/public/kontakt.html')
res.flash("success", "Ihre Webseite wurde erstellt, aber noch nicht veröffentlicht. Bitte fahren Sie mit Schritten 2 und 3 fort, um Ihre Webseite zu veröffentlichen.")
res.redirect('/account/updateInformation?id='+newInformation.getId()+'&s=n')
} }
callback(null) res.redirect('/account/newInformation')
}) } else {
let newPagesData = newPages.data
//res.flash("success", "Ihre Webseite wurde erstellt, aber noch nicht veröffentlicht. Bitte fahren Sie mit Schritten 2 und 3 fort, um Ihre Webseite zu veröffentlichen.")
res.flash("success", "Your website will be published AFTER you complete your website by following the provided guideline below."+
"\r\n Your website URL: "+tpGitlabPagesURL+newPagesData.path_with_namespace+"/home/")
res.redirect('/account/updateInformation?id='+newPagesData.id)
}
} }
], function (err) { ], function (err) {
if(err) console.log(err) if(err) console.log(err)
...@@ -548,51 +530,33 @@ module.exports = function (app, config, passport, i18n) { ...@@ -548,51 +530,33 @@ module.exports = function (app, config, passport, i18n) {
} }
}) })
app.get('/updateInformation', function(req, res){ app.get('/updateInformation', async function(req, res){
if(!req.isAuthenticated() && !loggedInUser) { if(!req.isAuthenticated() && !loggedInUser) {
res.redirect('/login') res.redirect('/login')
} else { } else {
if(!req.query.id) { if(!req.query.id) {
res.redirect('/account/services') res.redirect('/account/services')
} else { } else {
gitlab.getUserProjects(loggedInUser.getGitlabUserId(), function(data){ let project = await gitlab.getProjectById(req.query.id)
if (data.error) { if (!project) {
res.status(500).render(lang+'/500', { error: data.data }) console.log(" =================== error or no project found")
} else { res.redirect('/account/services')
// quick way to decide whether a website is already published or not } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
let informationStatus console.log(" =================== not your project")
if(req.query.s != "y" && req.query.s != "n") { res.redirect('/account/services')
res.redirect('/account/services') } else {
} else { let curInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, project.name, project.description,
if(req.query.s == "y") { project.avatar_url, project.path_with_namespace)
informationStatus = true
} else if(req.query.s == "n") { res.render(lang+'/account/updateInformation', {
informationStatus = false user: loggedInUser,
} information: curInformation
let gitlabData = data.data })
let curInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, null, null, null, null, null, null, informationStatus) }
for(let i = 0; i < gitlabData.length; i++){
if (gitlabData[i].id == req.query.id) {
curInformation.setName(gitlabData[i].name)
curInformation.setDesc(gitlabData[i].description)
curInformation.setLogo(gitlabData[i].avatar_url)
curInformation.setPath(gitlabData[i].path)
curInformation.setSettingUrl(tpGitlabURL+gitlabData[i].path_with_namespace+'/-/edit/master/public/settings.js')
curInformation.setKontaktUrl(tpGitlabURL+gitlabData[i].path_with_namespace+'/-/edit/master/public/kontakt.html')
break
}
}
res.render(lang+'/account/updateInformation', {
user: loggedInUser,
information: curInformation
})
}
}
})
} }
} }
}) })
app.post('/updateInformation', function(req, res){ app.post('/updateInformation', function(req, res){
if(!req.isAuthenticated() && !loggedInUser) { if(!req.isAuthenticated() && !loggedInUser) {
res.redirect('/login') res.redirect('/login')
...@@ -603,13 +567,9 @@ module.exports = function (app, config, passport, i18n) { ...@@ -603,13 +567,9 @@ module.exports = function (app, config, passport, i18n) {
} else { } else {
let projectName = req.body.name.toLowerCase().replace(/\s/g, '-') let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
let projectDesc = req.body.description let projectDesc = req.body.description
let isProjectPublished = true let updatedInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, projectName, projectDesc, null, null)
if (req.body.isPublished == "false") {
isProjectPublished = false
}
let updatedInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, projectName, projectDesc, null, null, null, null, isProjectPublished)
let newLogoFile let newLogoFile
async.waterfall([ async.waterfall([
function(callback){ // upload logo function(callback){ // upload logo
if(!req.files) { if(!req.files) {
...@@ -622,26 +582,21 @@ module.exports = function (app, config, passport, i18n) { ...@@ -622,26 +582,21 @@ module.exports = function (app, config, passport, i18n) {
}) })
} }
}, },
function(newLogoFile, callback){ // update gitlab page async function(newLogoFile, callback){ // update gitlab page
gitlab.updateProject(updatedInformation, newLogoFile, function(data){ let updatedPages = await gitlab.updateProject(updatedInformation, newLogoFile)
let result = data.data let pagesData = updatedPages.data
if (data.error) { if (pagesData.error) {
if(result.message.name == "has already been taken") { if(pagesData.message.name == "has already been taken") {
res.flash("error", "Der Projektname ist bereits vergeben, bitte wählen Sie einen anderen Namen.") res.flash("error", "Der Projektname ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
} else {
res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
}
} else { } else {
updatedInformation.setLogo(result.avatar_url) res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
updatedInformation.setPath(result.path)
updatedInformation.setSettingUrl(tpGitlabURL+result.namespace.path+'/'+result.name+'/-/edit/master/public/settings.js')
updatedInformation.setKontaktUrl(tpGitlabURL+result.namespace.path+'/'+result.name+'/-/edit/master/public/kontakt.html')
res.flash("success", "Your website has been updated")
} }
res.redirect('/account/updateInformation?id='+updatedInformation.getId()) } else {
updatedInformation.setLogo(pagesData.avatar_url)
callback(null) updatedInformation.setPath(pagesData.path)
}) res.flash("success", "Your website has been updated")
}
res.redirect('/account/updateInformation?id='+updatedInformation.getId())
} }
], function (err) { ], function (err) {
if(err) console.log(err) if(err) console.log(err)
...@@ -657,38 +612,6 @@ module.exports = function (app, config, passport, i18n) { ...@@ -657,38 +612,6 @@ module.exports = function (app, config, passport, i18n) {
// RS: delete projektInformation? // RS: delete projektInformation?
app.post('/sendPublishRequest', function(req, res) {
if (!req.isAuthenticated() && loggedInUser) {
res.redirect('/login')
} else {
let emailAddress = loggedInUser.getEmail()
let supportAddress = "support-transfer@hft-stuttgart.de"
let projectName = req.body.projectName
let emailContent = "Guten Tag, \n\nhiermit beantrage Ich die Freischaltung einer Webseite auf dem Transferportal für folgendes Projekt: \n"
+projectName+"\n\nVielen Dank,\n"+loggedInUser.getFullName()
let emailSubject = "M4_LAB Anfrage zur Veröffentlichung einer neuen Webseite"
async.waterfall([
function(done) {
mailer.options.to = supportAddress
mailer.options.cc = emailAddress
mailer.options.subject = emailSubject
mailer.options.text = emailContent
mailer.transport.sendMail(mailer.options, function(err) {
done(err, 'done')
})
}
], function(err) {
if (err) {
console.log(err)
res.send('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.')
}
else {
res.send('Vielen Dank für Ihre Anfrage. Eine Kopie Ihrer Anfrage wurde an ' + emailAddress + ' versandt.')
}
})
}
})
// ============= NEW USERS REGISTRATION =========================== // ============= NEW USERS REGISTRATION ===========================
app.get('/registration', function(req, res) { app.get('/registration', function(req, res) {
res.render(lang+'/account/registration') res.render(lang+'/account/registration')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment