Gitlab Community Edition Instance

Commit 506dbf01 authored by hholder's avatar hholder
Browse files

add images correctly

parent e9acbd25
......@@ -8,12 +8,6 @@ env:
jobs:
include:
- env: task=npm-test
node_js:
- 6
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version "$YARN_VERSION"
- export PATH="$HOME/.yarn/bin:$PATH"
- env: task=npm-test
node_js:
- 8
......
This diff is collapsed.
#!/usr/bin/env node
// First configure the logger so it does not spam the console
const logger = require("../lib/logger");
logger.transports.forEach((transport) => transport.level = "warning")
const logger = require('../lib/logger')
logger.transports.forEach((transport) => {
transport.level = 'warning'
})
const models = require("../lib/models/");
const readline = require("readline-sync");
const minimist = require("minimist");
const models = require('../lib/models/')
const readline = require('readline-sync')
const minimist = require('minimist')
function showUsage(tips) {
console.log(`${tips}
function showUsage (tips) {
console.log(`${tips}
Command-line utility to create users for email-signin.
Usage: bin/manage_users [--pass password] (--add | --del) user-email
Options:
--add Add user with the specified user-email
--del Delete user with specified user-email
--reset Reset user password with specified user-email
--pass Use password from cmdline rather than prompting
`);
process.exit(1);
Options:
--add\tAdd user with the specified user-email
--del\tDelete user with specified user-email
--reset\tReset user password with specified user-email
--pass\tUse password from cmdline rather than prompting
`)
process.exit(1)
}
function getPass(argv, action) {
// Find whether we use cmdline or prompt password
if(typeof argv["pass"] !== 'string') {
return readline.question(`Password for ${argv[action]}:`, {hideEchoBack: true});
}
console.log("Using password from commandline...");
return argv["pass"];
function getPass (argv, action) {
// Find whether we use cmdline or prompt password
if (typeof argv['pass'] !== 'string') {
return readline.question(`Password for ${argv[action]}:`, { hideEchoBack: true })
}
console.log('Using password from commandline...')
return argv['pass']
}
// Using an async function to be able to use await inside
async function createUser(argv) {
const existing_user = await models.User.findOne({where: {email: argv["add"]}});
// Cannot create already-existing users
if(existing_user != undefined) {
console.log(`User with e-mail ${existing_user.email} already exists! Aborting ...`);
process.exit(1);
}
const pass = getPass(argv, "add");
// Lets try to create, and check success
const ref = await models.User.create({email: argv["add"], password: pass});
if(ref == undefined) {
console.log(`Could not create user with email ${argv["add"]}`);
process.exit(1);
} else
console.log(`Created user with email ${argv["add"]}`);
async function createUser (argv) {
const existingUser = await models.User.findOne({ where: { email: argv['add'] } })
// Cannot create already-existing users
if (existingUser !== undefined) {
console.log(`User with e-mail ${existingUser.email} already exists! Aborting ...`)
process.exit(1)
}
const pass = getPass(argv, 'add')
// Lets try to create, and check success
const ref = await models.User.create({ email: argv['add'], password: pass })
if (ref === undefined) {
console.log(`Could not create user with email ${argv['add']}`)
process.exit(1)
} else { console.log(`Created user with email ${argv['add']}`) }
}
// Using an async function to be able to use await inside
async function deleteUser(argv) {
// Cannot delete non-existing users
const existing_user = await models.User.findOne({where: {email: argv["del"]}});
if(existing_user === undefined) {
console.log(`User with e-mail ${argv["del"]} does not exist, cannot delete`);
process.exit(1);
}
// Sadly .destroy() does not return any success value with all
// backends. See sequelize #4124
await existing_user.destroy();
console.log(`Deleted user ${argv["del"]} ...`);
async function deleteUser (argv) {
// Cannot delete non-existing users
const existingUser = await models.User.findOne({ where: { email: argv['del'] } })
if (existingUser === undefined) {
console.log(`User with e-mail ${argv['del']} does not exist, cannot delete`)
process.exit(1)
}
// Sadly .destroy() does not return any success value with all
// backends. See sequelize #4124
await existingUser.destroy()
console.log(`Deleted user ${argv['del']} ...`)
}
// Using an async function to be able to use await inside
async function resetUser(argv) {
const existing_user = await models.User.findOne({where: {email: argv["reset"]}});
// Cannot reset non-existing users
if(existing_user == undefined) {
console.log(`User with e-mail ${argv["reset"]} does not exist, cannot reset`);
process.exit(1);
}
const pass = getPass(argv, "reset");
// set password and save
existing_user.password = pass;
await existing_user.save();
console.log(`User with email ${argv["reset"]} password has been reset`);
async function resetUser (argv) {
const existingUser = await models.User.findOne({ where: { email: argv['reset'] } })
// Cannot reset non-existing users
if (existingUser === undefined) {
console.log(`User with e-mail ${argv['reset']} does not exist, cannot reset`)
process.exit(1)
}
const pass = getPass(argv, 'reset')
// set password and save
existingUser.password = pass
await existingUser.save()
console.log(`User with email ${argv['reset']} password has been reset`)
}
const options = {
add: createUser,
del: deleteUser,
reset: resetUser,
};
add: createUser,
del: deleteUser,
reset: resetUser
}
// Perform commandline-parsing
const argv = minimist(process.argv.slice(2));
const argv = minimist(process.argv.slice(2))
const keys = Object.keys(options);
const opts = keys.filter((key) => argv[key] !== undefined);
const action = opts[0];
const keys = Object.keys(options)
const opts = keys.filter((key) => argv[key] !== undefined)
const action = opts[0]
// Check for options missing
if (opts.length === 0) {
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`);
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`)
}
// Check if both are specified
if (opts.length > 1) {
showUsage(`You cannot ${action.join(' and ')} at the same time!`);
showUsage(`You cannot ${action.join(' and ')} at the same time!`)
}
// Check if not string
if (typeof argv[action] !== 'string') {
showUsage(`You must follow an email after --${action}`);
showUsage(`You must follow an email after --${action}`)
}
// Call respective processing functions
options[action](argv).then(function() {
process.exit(0);
});
options[action](argv).then(function () {
process.exit(0)
})
......@@ -66,7 +66,8 @@ module.exports = {
s3: {
accessKeyId: undefined,
secretAccessKey: undefined,
region: undefined
region: undefined,
endpoint: undefined
},
minio: {
accessKey: undefined,
......
'use strict'
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils')
const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
module.exports = {
sourceURL: process.env.CMD_SOURCE_URL,
......@@ -40,7 +40,8 @@ module.exports = {
s3: {
accessKeyId: process.env.CMD_S3_ACCESS_KEY_ID,
secretAccessKey: process.env.CMD_S3_SECRET_ACCESS_KEY,
region: process.env.CMD_S3_REGION
region: process.env.CMD_S3_REGION,
endpoint: process.env.CMD_S3_ENDPOINT
},
minio: {
accessKey: process.env.CMD_MINIO_ACCESS_KEY,
......
'use strict'
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils')
const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
module.exports = {
domain: process.env.HMD_DOMAIN,
......
......@@ -4,11 +4,11 @@
const crypto = require('crypto')
const fs = require('fs')
const path = require('path')
const {merge} = require('lodash')
const { merge } = require('lodash')
const deepFreeze = require('deep-freeze')
const {Environment, Permission} = require('./enum')
const { Environment, Permission } = require('./enum')
const logger = require('../logger')
const {getGitCommit, getGitHubURL} = require('./utils')
const { getGitCommit, getGitHubURL } = require('./utils')
const appRootPath = path.resolve(__dirname, '../../')
const env = process.env.NODE_ENV || Environment.development
......@@ -17,7 +17,7 @@ const debugConfig = {
}
// Get version string from package.json
const {version, repository} = require(path.join(appRootPath, 'package.json'))
const { version, repository } = require(path.join(appRootPath, 'package.json'))
const commitID = getGitCommit(appRootPath)
const sourceURL = getGitHubURL(repository.url, commitID || version)
......@@ -159,8 +159,8 @@ if (Object.keys(process.env).toString().indexOf('HMD_') !== -1) {
if (config.sessionSecret === 'secret') {
logger.warn('Session secret not set. Using random generated one. Please set `sessionSecret` in your config.js file. All users will be logged out.')
config.sessionSecret = crypto.randomBytes(Math.ceil(config.sessionSecretLen / 2)) // generate crypto graphic random number
.toString('hex') // convert to hexadecimal format
.slice(0, config.sessionSecretLen) // return required number of characters
.toString('hex') // convert to hexadecimal format
.slice(0, config.sessionSecretLen) // return required number of characters
}
// Validate upload upload providers
......
'use strict'
const {toBooleanConfig} = require('./utils')
const { toBooleanConfig } = require('./utils')
module.exports = {
debug: toBooleanConfig(process.env.DEBUG),
......
'use strict'
// history
// external modules
var LZString = require('lz-string')
var LZString = require('@hackmd/lz-string')
// core
var config = require('./config')
......
......@@ -30,14 +30,14 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
if (typeof email !== 'string') {
email = '' + name + '@example.com'
}
name=encodeURIComponent(name)
name = encodeURIComponent(name)
let hash = crypto.createHash('md5')
hash.update(email.toLowerCase())
let hexDigest = hash.digest('hex')
if (email !== '' && config.allowGravatar) {
photo = 'https://www.gravatar.com/avatar/' + hexDigest;
photo = 'https://www.gravatar.com/avatar/' + hexDigest
if (big) {
photo += '?s=400'
} else {
......
'use strict'
const {createLogger, format, transports} = require('winston')
const { createLogger, format, transports } = require('winston')
const logger = createLogger({
level: 'debug',
......
......@@ -18,8 +18,8 @@ module.exports = {
down: function (queryInterface, Sequelize) {
return queryInterface.removeColumn('Notes', 'lastchangeAt')
.then(function () {
return queryInterface.removeColumn('Notes', 'lastchangeuserId')
})
.then(function () {
return queryInterface.removeColumn('Notes', 'lastchangeuserId')
})
}
}
'use strict'
module.exports = {
up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT('long')})
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT('long')})
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT('long')})
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT('long')})
up: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT('long') })
await queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT('long') })
await queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT('long') })
await queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT('long') })
},
down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT})
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT})
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT})
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT})
down: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT })
await queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT })
await queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT })
await queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT })
}
}
'use strict'
module.exports = {
up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT('long')})
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT('long')})
up: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT('long') })
await queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT('long') })
},
down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT})
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT})
down: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT })
await queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT })
}
}
'use strict'
module.exports = {
up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'permission', {type: Sequelize.ENUM('freely', 'editable', 'limited', 'locked', 'protected', 'private')})
up: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'limited', 'locked', 'protected', 'private') })
},
down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'permission', {type: Sequelize.ENUM('freely', 'editable', 'locked', 'private')})
down: async function (queryInterface, Sequelize) {
await queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'locked', 'private') })
}
}
......@@ -18,25 +18,25 @@ module.exports = function (sequelize, DataTypes) {
unique: true,
fields: ['noteId', 'userId']
}
],
classMethods: {
associate: function (models) {
Author.belongsTo(models.Note, {
foreignKey: 'noteId',
as: 'note',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
Author.belongsTo(models.User, {
foreignKey: 'userId',
as: 'user',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
}
}
]
})
Author.associate = function (models) {
Author.belongsTo(models.Note, {
foreignKey: 'noteId',
as: 'note',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
Author.belongsTo(models.User, {
foreignKey: 'userId',
as: 'user',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
}
return Author
}
......@@ -3,14 +3,16 @@
var fs = require('fs')
var path = require('path')
var Sequelize = require('sequelize')
const {cloneDeep} = require('lodash')
const { cloneDeep } = require('lodash')
// core
var config = require('../config')
var logger = require('../logger')
var dbconfig = cloneDeep(config.db)
dbconfig.logging = config.debug ? logger.info : false
dbconfig.logging = config.debug ? (data) => {
logger.info(data)
} : false
var sequelize = null
......@@ -39,13 +41,13 @@ sequelize.processData = processData
var db = {}
fs.readdirSync(__dirname)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js')
})
.forEach(function (file) {
var model = sequelize.import(path.join(__dirname, file))
db[model.name] = model
})
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js')
})
.forEach(function (file) {
var model = sequelize.import(path.join(__dirname, file))
db[model.name] = model
})
Object.keys(db).forEach(function (modelName) {
if ('associate' in db[modelName]) {
......
This diff is collapsed.
......@@ -7,6 +7,8 @@ var childProcess = require('child_process')
var shortId = require('shortid')
var path = require('path')
var Op = Sequelize.Op
// core
var config = require('../config')
var logger = require('../logger')
......@@ -97,214 +99,212 @@ module.exports = function (sequelize, DataTypes) {
this.setDataValue('authorship', value ? JSON.stringify(value) : value)
}
}
}, {
classMethods: {
associate: function (models) {
Revision.belongsTo(models.Note, {
foreignKey: 'noteId',
as: 'note',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
},
getNoteRevisions: function (note, callback) {
Revision.findAll({
where: {
noteId: note.id
},
order: [['createdAt', 'DESC']]
}).then(function (revisions) {
var data = []
for (var i = 0, l = revisions.length; i < l; i++) {
var revision = revisions[i]
data.push({
time: moment(revision.createdAt).valueOf(),
length: revision.length
})
}
callback(null, data)
}).catch(function (err) {
callback(err, null)
})
})
Revision.associate = function (models) {
Revision.belongsTo(models.Note, {
foreignKey: 'noteId',
as: 'note',
constraints: false,
onDelete: 'CASCADE',
hooks: true
})
}
Revision.getNoteRevisions = function (note, callback) {
Revision.findAll({
where: {
noteId: note.id
},
getPatchedNoteRevisionByTime: function (note, time, callback) {
// find all revisions to prepare for all possible calculation
Revision.findAll({
where: {
noteId: note.id
},
order: [['createdAt', 'DESC']]
}).then(function (revisions) {
if (revisions.length <= 0) return callback(null, null)
// measure target revision position
Revision.count({
where: {
noteId: note.id,
createdAt: {
$gte: time
}
},
order: [['createdAt', 'DESC']]
}).then(function (count) {
if (count <= 0) return callback(null, null)
sendDmpWorker({
msg: 'get revision',
revisions: revisions,
count: count
}, callback)
}).catch(function (err) {
return callback(err, null)
})
}).catch(function (err) {
return callback(err, null)
order: [['createdAt', 'DESC']]
}).then(function (revisions) {
var data = []
for (var i = 0, l = revisions.length; i < l; i++) {