Merge branch 'develop' into feature/rtl-interface-client
This commit is contained in:
commit
946b863bab
@ -109,6 +109,7 @@ public abstract class BaseStartup
|
||||
.AddBaseDbContextPool<TelegramDbContext>()
|
||||
.AddBaseDbContextPool<FirebaseDbContext>()
|
||||
.AddBaseDbContextPool<CustomDbContext>()
|
||||
.AddBaseDbContextPool<UrlShortenerDbContext>()
|
||||
.AddBaseDbContextPool<WebstudioDbContext>()
|
||||
.AddBaseDbContextPool<InstanceRegistrationContext>()
|
||||
.AddBaseDbContextPool<IntegrationEventLogContext>()
|
||||
|
@ -52,6 +52,7 @@ public class BaseWorkerStartup
|
||||
services.AddBaseDbContextPool<TelegramDbContext>();
|
||||
services.AddBaseDbContextPool<FirebaseDbContext>();
|
||||
services.AddBaseDbContextPool<CustomDbContext>();
|
||||
services.AddBaseDbContextPool<UrlShortenerDbContext>();
|
||||
services.AddBaseDbContextPool<WebstudioDbContext>();
|
||||
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
||||
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
||||
|
@ -26,9 +26,11 @@
|
||||
|
||||
namespace ASC.Core.Common.EF.Context;
|
||||
|
||||
public class UrlShortenerFakeDbContext : DbContext
|
||||
public class UrlShortenerDbContext : DbContext
|
||||
{
|
||||
public UrlShortenerFakeDbContext(DbContextOptions<UrlShortenerFakeDbContext> dbContextOptions) : base(dbContextOptions)
|
||||
public DbSet<ShortLink> ShortLinks { get; set; }
|
||||
|
||||
public UrlShortenerDbContext(DbContextOptions<UrlShortenerDbContext> dbContextOptions) : base(dbContextOptions)
|
||||
{
|
||||
|
||||
}
|
@ -26,9 +26,9 @@
|
||||
|
||||
|
||||
namespace ASC.Core.Common.EF.Model;
|
||||
public class ShortLinks
|
||||
public class ShortLink
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string Short { get; set; }
|
||||
public string Link { get; set; }
|
||||
}
|
||||
@ -46,7 +46,7 @@ public static class ShortLinksExtension
|
||||
|
||||
public static void MySqlAddShortLinks(this ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ShortLinks>(entity =>
|
||||
modelBuilder.Entity<ShortLink>(entity =>
|
||||
{
|
||||
entity.ToTable("short_links")
|
||||
.HasCharSet("utf8")
|
||||
@ -61,7 +61,7 @@ public static class ShortLinksExtension
|
||||
entity.Property(e => e.Id)
|
||||
.HasColumnName("id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int(10)");
|
||||
.HasColumnType("bigint(19)");
|
||||
|
||||
entity.Property(e => e.Short)
|
||||
.HasColumnName("short")
|
||||
@ -80,7 +80,7 @@ public static class ShortLinksExtension
|
||||
|
||||
public static void PgSqlAddShortLinks(this ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ShortLinks>(entity =>
|
||||
modelBuilder.Entity<ShortLink>(entity =>
|
||||
{
|
||||
entity.ToTable("short_links")
|
||||
.HasCharSet("utf8")
|
||||
@ -95,7 +95,7 @@ public static class ShortLinksExtension
|
||||
entity.Property(e => e.Id)
|
||||
.HasColumnName("id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int(10)");
|
||||
.HasColumnType("bigint(19)");
|
||||
|
||||
entity.Property(e => e.Short)
|
||||
.HasColumnName("short")
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,102 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const queryConsts = require('./sqlConsts');
|
||||
const shortUrl = require('./urlShortener');
|
||||
const auth = require('../middleware/auth');
|
||||
const query = require('./sql');
|
||||
const log = require('./log');
|
||||
const co = require('co');
|
||||
|
||||
const linkReg = /http(s)?:\/\/.*/;
|
||||
|
||||
let urls = [];
|
||||
|
||||
function processError(err, res, code = 400) {
|
||||
log.error((err && err.message) ? err.message : err);
|
||||
res.sendStatus(code);
|
||||
}
|
||||
|
||||
function redirect(req, res) {
|
||||
let short = req.params[0];
|
||||
if (short.length > 12)
|
||||
{ res.sendStatus(400); return; }
|
||||
|
||||
let id = shortUrl.decode(short);
|
||||
if (!id) { res.sendStatus(400); return; }
|
||||
|
||||
|
||||
query(queryConsts.find, [id])
|
||||
.then((result) => {
|
||||
log.info("redirecting (" + short + ") to " + result[0].link);
|
||||
res.redirect(result[0].link);
|
||||
})
|
||||
.catch((err) => processError(err, res));
|
||||
}
|
||||
|
||||
function make(req, res) {
|
||||
if (!auth(req)) { res.sendStatus(401); return; }
|
||||
|
||||
res.contentType('text');
|
||||
|
||||
if (!req.query.url || !linkReg.test(req.query.url)) { processError(new Error('Empty or wrong url'), res, 400); return }
|
||||
|
||||
let link = req.query.url;
|
||||
|
||||
co(function* () {
|
||||
var result = yield query(queryConsts.exists, [link]);
|
||||
|
||||
var key;
|
||||
if (result.length) {
|
||||
if (result.short) {
|
||||
res.write(result[0].short);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
key = shortUrl.encode(result[0].id);
|
||||
log.info("already created shortlink (" + key + ") for " + link);
|
||||
} else {
|
||||
if (urls.find(r => r === link)) {
|
||||
processError(new Error('Link is already being made'), res, 500);
|
||||
return;
|
||||
}
|
||||
result = yield query(queryConsts.insert, [link]);
|
||||
key = shortUrl.encode(result.insertId);
|
||||
log.info("creted new shortlink (" + key + ") for " + link);
|
||||
yield query(queryConsts.update, [key, result.insertId]);
|
||||
}
|
||||
|
||||
urls = urls.filter((item) => item !== link);
|
||||
|
||||
res.write(key);
|
||||
res.end();
|
||||
}).catch((err) => processError(err, res));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
redirect: redirect,
|
||||
make: make
|
||||
};
|
@ -1,115 +0,0 @@
|
||||
const winston = require("winston"),
|
||||
WinstonCloudWatch = require('winston-cloudwatch');
|
||||
|
||||
require("winston-daily-rotate-file");
|
||||
|
||||
const path = require("path");
|
||||
const config = require("../config");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const { randomUUID } = require('crypto');
|
||||
const date = require('date-and-time');
|
||||
|
||||
let logpath = config.get("logPath");
|
||||
if(logpath != null)
|
||||
{
|
||||
if(!path.isAbsolute(logpath))
|
||||
{
|
||||
logpath = path.join(__dirname, "..", logpath);
|
||||
}
|
||||
}
|
||||
|
||||
const fileName = logpath ? path.join(logpath, "web.shorturl.%DATE%.log") : path.join(__dirname, "..", "..", "..", "Logs", "web.shorturl.%DATE%.log");
|
||||
const dirName = path.dirname(fileName);
|
||||
|
||||
const aws = config.get("aws").cloudWatch;
|
||||
|
||||
const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName;
|
||||
|
||||
if (!fs.existsSync(dirName)) {
|
||||
fs.mkdirSync(dirName);
|
||||
}
|
||||
|
||||
var options = {
|
||||
file: {
|
||||
filename: fileName,
|
||||
datePattern: "MM-DD",
|
||||
handleExceptions: true,
|
||||
humanReadableUnhandledException: true,
|
||||
zippedArchive: true,
|
||||
maxSize: "50m",
|
||||
maxFiles: "30d",
|
||||
json: true,
|
||||
},
|
||||
console: {
|
||||
level: "debug",
|
||||
handleExceptions: true,
|
||||
json: false,
|
||||
colorize: true,
|
||||
},
|
||||
cloudWatch: {
|
||||
name: 'aws',
|
||||
level: "debug",
|
||||
logStreamName: () => {
|
||||
const hostname = os.hostname();
|
||||
const now = new Date();
|
||||
const guid = randomUUID();
|
||||
const dateAsString = date.format(now, 'YYYY/MM/DDTHH.mm.ss');
|
||||
|
||||
return logStreamName.replace("${hostname}", hostname)
|
||||
.replace("${applicationContext}", "UrlShortener")
|
||||
.replace("${guid}", guid)
|
||||
.replace("${date}", dateAsString);
|
||||
},
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
awsOptions: {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyId,
|
||||
secretAccessKey: secretAccessKey
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//const fileTransport = new winston.transports.DailyRotateFile(options.file);
|
||||
|
||||
let transports = [
|
||||
new winston.transports.Console(options.console),
|
||||
new winston.transports.DailyRotateFile(options.file)
|
||||
];
|
||||
|
||||
if (aws != null && aws.accessKeyId !== '')
|
||||
{
|
||||
transports.push(new WinstonCloudWatch(options.cloudWatch));
|
||||
}
|
||||
|
||||
//winston.exceptions.handle(fileTransport);
|
||||
|
||||
const customFormat = winston.format(info => {
|
||||
const now = new Date();
|
||||
|
||||
info.date = date.format(now, 'YYYY-MM-DD HH:mm:ss');
|
||||
info.applicationContext = "UrlShortener";
|
||||
info.level = info.level.toUpperCase();
|
||||
|
||||
const hostname = os.hostname();
|
||||
|
||||
info["instance-id"] = hostname;
|
||||
|
||||
return info;
|
||||
})();
|
||||
|
||||
module.exports = new winston.createLogger({
|
||||
format: winston.format.combine(
|
||||
customFormat,
|
||||
winston.format.json()
|
||||
),
|
||||
transports: transports,
|
||||
exitOnError: false,
|
||||
});
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const sql = require('mysql2');
|
||||
const log = require('./log');
|
||||
const config = require('../config');
|
||||
const co = require('co');
|
||||
|
||||
var connection;
|
||||
|
||||
function createNewConnection() {
|
||||
return new Promise((resolve, reject) => {
|
||||
log.info("establishing new connection");
|
||||
connection = sql.createConnection(config.get("sql"));
|
||||
connect().then(resolve).catch(reject);
|
||||
connection.on('error', onError);
|
||||
});
|
||||
}
|
||||
|
||||
function connect() {
|
||||
return new Promise((resolve, reject) => connection.connect(function(err) {
|
||||
if (err) {
|
||||
connection = null;
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("connected to sql");
|
||||
resolve();
|
||||
}));
|
||||
}
|
||||
|
||||
function reconnect() {
|
||||
co(function* () {
|
||||
var shouldReconnect = true;
|
||||
var attempts = 0;
|
||||
|
||||
while(shouldReconnect) {
|
||||
try {
|
||||
yield new Promise((resolve, reject) => setTimeout(resolve, 1000 * 5));
|
||||
attempts++;
|
||||
log.warn("reconnecting to sql, attempt: " + attempts);
|
||||
yield createNewConnection();
|
||||
shouldReconnect = false;
|
||||
} catch(err) {
|
||||
log.error(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onError(err) {
|
||||
log.error("sql error: " + err.code);
|
||||
if (err.fatal) {
|
||||
reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
const query = (query, params) => new Promise((resolve, reject) => {
|
||||
co(function* () {
|
||||
if (!connection) yield createNewConnection();
|
||||
}).catch(reject);
|
||||
|
||||
connection.query(query, params, function(err, res) {
|
||||
if (err) reject(err);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = query;
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
module.exports = {
|
||||
exists: "SELECT short,id FROM short_links WHERE link = ?",
|
||||
insert: "INSERT INTO short_links SET link = ?",
|
||||
update: "UPDATE short_links SET short = ? WHERE id = ?",
|
||||
find: "SELECT link FROM short_links WHERE id = ?",
|
||||
};
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* ShortURL (https://github.com/delight-im/ShortURL)
|
||||
* Copyright (c) delight.im (https://www.delight.im/)
|
||||
* Licensed under the MIT License (https://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
/**
|
||||
* ShortURL: Bijective conversion between natural numbers (IDs) and short strings
|
||||
*
|
||||
* ShortURL.encode() takes an ID and turns it into a short string
|
||||
* ShortURL.decode() takes a short string and turns it into an ID
|
||||
*
|
||||
* Features:
|
||||
* + large alphabet (51 chars) and thus very short resulting strings
|
||||
* + proof against offensive words (removed 'a', 'e', 'i', 'o' and 'u')
|
||||
* + unambiguous (removed 'I', 'l', '1', 'O' and '0')
|
||||
*
|
||||
* Example output:
|
||||
* 123456789 <=> pgK8p
|
||||
*/
|
||||
|
||||
//'23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_'
|
||||
|
||||
var _alphabet = "5XzpDt6wZRdsTrJkSY_cgPyxN4j-fnb9WKBF8vh3GH72QqmLVCM",
|
||||
_base = _alphabet.length,
|
||||
_initial = _base * _base;
|
||||
|
||||
module.exports = {
|
||||
|
||||
encode: function(num) {
|
||||
num += _initial;
|
||||
var str = '';
|
||||
while (num > 0) {
|
||||
str = _alphabet.charAt(num % _base) + str;
|
||||
num = Math.floor(num / _base);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
decode: function(str) {
|
||||
var num = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
let index = _alphabet.indexOf(str.charAt(i));
|
||||
if (index < 0) return null;
|
||||
num = num * _base + index;
|
||||
}
|
||||
return num - _initial;
|
||||
}
|
||||
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"app":{
|
||||
"port": 9999,
|
||||
"appsettings": "../../../config",
|
||||
"environment": "Development"
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const nconf = require("nconf");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
nconf.argv()
|
||||
.env()
|
||||
.file("config", path.join(__dirname, 'config.json') );
|
||||
|
||||
getAndSaveAppsettings();
|
||||
|
||||
getAndSaveSql();
|
||||
|
||||
module.exports = nconf;
|
||||
|
||||
function getAndSaveAppsettings(){
|
||||
var appsettings = nconf.get("app").appsettings;
|
||||
if(!path.isAbsolute(appsettings)){
|
||||
appsettings =path.join(__dirname, appsettings);
|
||||
}
|
||||
|
||||
var env = nconf.get("app").environment;
|
||||
console.log('environment: ' + env);
|
||||
|
||||
nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json'));
|
||||
nconf.file("appsettings", path.join(appsettings, 'appsettings.json'));
|
||||
nconf.file("appsettingsServices", path.join(appsettings, 'appsettings.services.json'));
|
||||
}
|
||||
|
||||
function getAndSaveSql(){
|
||||
var sql = new Map();
|
||||
var connetionString = nconf.get("ConnectionStrings").default.connectionString;
|
||||
|
||||
var conf = connetionString.split(';');
|
||||
|
||||
for(let i = 0; i < conf.length; i++){
|
||||
var splited = conf[i].split('=');
|
||||
if(splited.Length < 2) continue;
|
||||
if(splited[0] != null){
|
||||
sql[splited[0]] = splited[1];
|
||||
}
|
||||
}
|
||||
nconf.set("sql", sql);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const express = require('express');
|
||||
const cookieParser = require('cookie-parser');
|
||||
|
||||
const short = require('./app/app');
|
||||
const log = require('./app/log');
|
||||
log.stream = {
|
||||
write: (message) => log.info(message)
|
||||
};
|
||||
|
||||
const sql = require('./app/sql');
|
||||
const query = require('./app/sqlConsts');
|
||||
const config = require('./config');
|
||||
const co = require('co');
|
||||
|
||||
var app = express();
|
||||
|
||||
app.use(cookieParser());
|
||||
|
||||
app.get('/', short.make);
|
||||
app.get('/*', short.redirect);
|
||||
|
||||
const port = config.get("app").port;
|
||||
|
||||
app.listen(port, () => log.info(`Server started on port: ${port}`));
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const
|
||||
config = require('../config'),
|
||||
crypto = require('crypto'),
|
||||
moment = require('moment');
|
||||
|
||||
const skey = config.get("core").machinekey;
|
||||
const trustInterval = 5 * 60 * 1000;
|
||||
|
||||
function check(req) {
|
||||
const authHeader = req.headers["authorization"] || req.cookies["authorization"];
|
||||
if(!authHeader) return false;
|
||||
|
||||
const splitted = authHeader.split(':');
|
||||
if (splitted.length < 3) return false;
|
||||
|
||||
const pkey = splitted[0].substr(4);
|
||||
const date = splitted[1];
|
||||
const orighash = splitted[2];
|
||||
|
||||
const timestamp = moment.utc(date, "YYYYMMDDHHmmss");
|
||||
if (moment.utc() - timestamp > trustInterval) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasher = crypto.createHmac('sha1', skey);
|
||||
const hash = hasher.update(date + "\n" + pkey);
|
||||
|
||||
if (hash.digest('base64') !== orighash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = (req) => {
|
||||
return check(req);
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "urlshortener-service",
|
||||
"version": "1.0.0",
|
||||
"description": "A service which makes short url and handles redirections.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.199.0",
|
||||
"co": "^4.6.0",
|
||||
"cookie-parser": "^1.4.3",
|
||||
"date-and-time": "^2.4.1",
|
||||
"express": "^4.16.3",
|
||||
"moment": "^2.22.2",
|
||||
"mysql2": "^2.1.0",
|
||||
"nconf": "^0.10.0",
|
||||
"request": "^2.88.0",
|
||||
"winston": "^3.8.2",
|
||||
"winston-cloudwatch": "^6.1.1",
|
||||
"winston-daily-rotate-file": "^4.5.5"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,27 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
@ -49,4 +49,4 @@ if (!Path.IsPathRooted(conf.Path))
|
||||
}
|
||||
|
||||
var migrationCreator = new MigrationCreator(app.Services);
|
||||
migrationCreator.RunCreateMigrations(conf);
|
||||
migrationCreator.RunCreateMigrations(conf);
|
||||
|
@ -1,27 +1,27 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
@ -48,4 +48,4 @@ foreach (var providerInfo in providersInfo.Providers)
|
||||
{
|
||||
var migrationCreator = new MigrationRunner(app.Services);
|
||||
migrationCreator.RunApplyMigrations(AppContext.BaseDirectory, providerInfo, providersInfo.TeamlabsiteProviders.SingleOrDefault(q => q.Provider == providerInfo.Provider), configurationInfo);
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ public class MigrationContext : DbContext
|
||||
public DbSet<DbFilesLink> FilesLink { get; set; }
|
||||
public DbSet<DbFilesProperties> FilesProperties { get; set; }
|
||||
public DbSet<FilesConverts> FilesConverts { get; set; }
|
||||
public DbSet<ShortLink> ShortLink { get; set; }
|
||||
public MigrationContext(DbContextOptions<MigrationContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
@ -159,6 +160,7 @@ public class MigrationContext : DbContext
|
||||
.AddDbWebhooks()
|
||||
.AddWebhooksConfig()
|
||||
.AddWebhooksLog()
|
||||
.AddShortLinks()
|
||||
.AddDbFunctions();
|
||||
}
|
||||
}
|
@ -56,7 +56,8 @@ public class Startup
|
||||
services.AddBaseDbContextPool<UserDbContext>();
|
||||
services.AddBaseDbContextPool<TelegramDbContext>();
|
||||
services.AddBaseDbContextPool<FirebaseDbContext>();
|
||||
services.AddBaseDbContextPool<CustomDbContext>();
|
||||
services.AddBaseDbContextPool<CustomDbContext>();
|
||||
services.AddBaseDbContextPool<UrlShortenerDbContext>();
|
||||
services.AddBaseDbContextPool<WebstudioDbContext>();
|
||||
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
||||
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
||||
|
@ -183,6 +183,10 @@ server {
|
||||
proxy_pass http://127.0.0.1:5001;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location ~* sh/(.*) {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
}
|
||||
|
||||
location /api/2.0 {
|
||||
location ~* /(files|privacyroom) {
|
||||
@ -268,11 +272,6 @@ server {
|
||||
rewrite apicache/(.*) /$1 break;
|
||||
proxy_pass http://127.0.0.1:5100;
|
||||
}
|
||||
|
||||
location /sh {
|
||||
rewrite sh/(.*) /$1 break;
|
||||
proxy_pass http://127.0.0.1:9999;
|
||||
}
|
||||
|
||||
location /healthchecks {
|
||||
rewrite /healthchecks/(.*)$ /$1 break;
|
||||
|
@ -4579,6 +4579,37 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
b.HasAnnotation("MySql:CharSet", "utf8");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.ShortLink", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint(19)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("Link")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("link")
|
||||
.UseCollation("utf8_bin");
|
||||
|
||||
b.Property<string>("Short")
|
||||
.HasColumnType("varchar(12)")
|
||||
.HasColumnName("short")
|
||||
.UseCollation("utf8_general_ci")
|
||||
.HasAnnotation("MySql:CharSet", "utf8");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PRIMARY");
|
||||
|
||||
b.HasIndex("Short")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("short_links", (string)null);
|
||||
|
||||
b
|
||||
.HasAnnotation("MySql:CharSet", "utf8")
|
||||
.HasAnnotation("Relational:Collation", "utf8_general_ci");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||
{
|
||||
b.Property<int>("TenantId")
|
||||
|
@ -1,4 +1,29 @@
|
||||
using System;
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
@ -1454,6 +1479,24 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "short_links",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<long>(type: "bigint(19)", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
@short = table.Column<string>(name: "short", type: "varchar(12)", nullable: true, collation: "utf8_general_ci")
|
||||
.Annotation("MySql:CharSet", "utf8"),
|
||||
link = table.Column<string>(type: "text", nullable: true, collation: "utf8_bin")
|
||||
.Annotation("MySql:CharSet", "utf8")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PRIMARY", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8")
|
||||
.Annotation("Relational:Collation", "utf8_general_ci");
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "files_converts",
|
||||
columns: new[] { "input", "output" },
|
||||
@ -2498,6 +2541,12 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
name: "visitdate",
|
||||
table: "webstudio_uservisit",
|
||||
column: "visitdate");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_short_links_short",
|
||||
table: "short_links",
|
||||
column: "short",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -2667,6 +2716,9 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenants_tenants");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "short_links");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4576,6 +4576,37 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
b.HasAnnotation("MySql:CharSet", "utf8");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.ShortLink", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint(19)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("Link")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("link")
|
||||
.UseCollation("utf8_bin");
|
||||
|
||||
b.Property<string>("Short")
|
||||
.HasColumnType("varchar(12)")
|
||||
.HasColumnName("short")
|
||||
.UseCollation("utf8_general_ci")
|
||||
.HasAnnotation("MySql:CharSet", "utf8");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PRIMARY");
|
||||
|
||||
b.HasIndex("Short")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("short_links", (string)null);
|
||||
|
||||
b
|
||||
.HasAnnotation("MySql:CharSet", "utf8")
|
||||
.HasAnnotation("Relational:Collation", "utf8_general_ci");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||
{
|
||||
b.Property<int>("TenantId")
|
||||
@ -5845,7 +5876,7 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
||||
.UseCollation("utf8_general_ci")
|
||||
.HasAnnotation("MySql:CharSet", "utf8");
|
||||
|
||||
b.Property<string>("FileShareOptions")
|
||||
b.Property<string>("Options")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("options")
|
||||
.UseCollation("utf8_general_ci")
|
||||
|
@ -4510,6 +4510,38 @@ namespace ASC.Migrations.PostgreSql.SaaS.Migrations
|
||||
b.ToTable("Regions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.ShortLink", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint(19)")
|
||||
.HasColumnName("id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("Link")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("link")
|
||||
.UseCollation("utf8_bin");
|
||||
|
||||
b.Property<string>("Short")
|
||||
.HasColumnType("varchar(12)")
|
||||
.HasColumnName("short")
|
||||
.UseCollation("utf8_general_ci")
|
||||
.HasAnnotation("MySql:CharSet", "utf8");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PRIMARY");
|
||||
|
||||
b.HasIndex("Short")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("short_links", (string)null);
|
||||
|
||||
b
|
||||
.HasAnnotation("MySql:CharSet", "utf8")
|
||||
.HasAnnotation("Relational:Collation", "utf8_general_ci");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||
{
|
||||
b.Property<int>("TenantId")
|
||||
@ -5718,7 +5750,7 @@ namespace ASC.Migrations.PostgreSql.SaaS.Migrations
|
||||
.HasColumnName("subject")
|
||||
.IsFixedLength();
|
||||
|
||||
b.Property<string>("FileShareOptions")
|
||||
b.Property<string>("Options")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("options");
|
||||
|
||||
|
@ -20,8 +20,6 @@ const PublicRoomBlock = (props) => {
|
||||
setEditLinkPanelIsVisible,
|
||||
} = props;
|
||||
|
||||
const [barIsVisible, setBarVisible] = useState(!isArchiveFolder);
|
||||
|
||||
const onAddNewLink = () => {
|
||||
setLinkParams({ isEdit: false });
|
||||
setEditLinkPanelIsVisible(true);
|
||||
@ -29,7 +27,7 @@ const PublicRoomBlock = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{barIsVisible && (
|
||||
{externalLinks.length > 0 && !isArchiveFolder && (
|
||||
<PublicRoomBar
|
||||
headerText={t("Files:PublicRoom")}
|
||||
bodyText={t("CreateEditRoomDialog:PublicRoomBarDescription")}
|
||||
|
@ -24,8 +24,6 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using UrlShortener = ASC.Web.Core.Utility.UrlShortener;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService;
|
||||
|
||||
[Scope]
|
||||
@ -68,7 +66,7 @@ public class FileStorageService //: IFileStorageService
|
||||
private readonly DocumentServiceConnector _documentServiceConnector;
|
||||
private readonly FileSharing _fileSharing;
|
||||
private readonly NotifyClient _notifyClient;
|
||||
private readonly UrlShortener _urlShortener;
|
||||
private readonly IUrlShortener _urlShortener;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly FileSharingAceHelper _fileSharingAceHelper;
|
||||
private readonly ConsumerFactory _consumerFactory;
|
||||
@ -123,7 +121,7 @@ public class FileStorageService //: IFileStorageService
|
||||
DocumentServiceConnector documentServiceConnector,
|
||||
FileSharing fileSharing,
|
||||
NotifyClient notifyClient,
|
||||
UrlShortener urlShortener,
|
||||
IUrlShortener urlShortener,
|
||||
IServiceProvider serviceProvider,
|
||||
FileSharingAceHelper fileSharingAceHelper,
|
||||
ConsumerFactory consumerFactory,
|
||||
@ -2564,7 +2562,7 @@ public class FileStorageService //: IFileStorageService
|
||||
|
||||
try
|
||||
{
|
||||
return await _urlShortener.Instance.GetShortenLinkAsync(shareLink);
|
||||
return await _urlShortener.GetShortenLinkAsync(shareLink);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -138,6 +138,7 @@ global using ASC.Web.Core.Notify;
|
||||
global using ASC.Web.Core.PublicResources;
|
||||
global using ASC.Web.Core.Quota;
|
||||
global using ASC.Web.Core.Users;
|
||||
global using ASC.Web.Core.Utility;
|
||||
global using ASC.Web.Core.Utility.Skins;
|
||||
global using ASC.Web.Core.WhiteLabel;
|
||||
global using ASC.Web.Files;
|
||||
|
@ -1,56 +1,56 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.Controllers;
|
||||
|
||||
[Scope]
|
||||
[DefaultRoute]
|
||||
[ApiController]
|
||||
public class PortalController : ControllerBase
|
||||
{
|
||||
protected Tenant Tenant { get { return _apiContext.Tenant; } }
|
||||
|
||||
private readonly ApiContext _apiContext;
|
||||
protected readonly UserManager _userManager;
|
||||
protected readonly TenantManager _tenantManager;
|
||||
protected readonly ITariffService _tariffService;
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly UrlShortener _urlShortener;
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly WebItemSecurity _webItemSecurity;
|
||||
protected readonly SecurityContext _securityContext;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly IMobileAppInstallRegistrator _mobileAppInstallRegistrator;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly LicenseReader _licenseReader;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly DocumentServiceLicense _documentServiceLicense;
|
||||
private readonly TenantExtra _tenantExtra;
|
||||
private readonly ILogger<PortalController> _log;
|
||||
namespace ASC.Web.Api.Controllers;
|
||||
|
||||
[Scope]
|
||||
[DefaultRoute]
|
||||
[ApiController]
|
||||
public class PortalController : ControllerBase
|
||||
{
|
||||
protected Tenant Tenant { get { return _apiContext.Tenant; } }
|
||||
|
||||
private readonly ApiContext _apiContext;
|
||||
protected readonly UserManager _userManager;
|
||||
protected readonly TenantManager _tenantManager;
|
||||
protected readonly ITariffService _tariffService;
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly IUrlShortener _urlShortener;
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly WebItemSecurity _webItemSecurity;
|
||||
protected readonly SecurityContext _securityContext;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly IMobileAppInstallRegistrator _mobileAppInstallRegistrator;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly LicenseReader _licenseReader;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly DocumentServiceLicense _documentServiceLicense;
|
||||
private readonly TenantExtra _tenantExtra;
|
||||
private readonly ILogger<PortalController> _log;
|
||||
private readonly IHttpClientFactory _clientFactory;
|
||||
private readonly ApiSystemHelper _apiSystemHelper;
|
||||
private readonly CoreSettings _coreSettings;
|
||||
@ -67,25 +67,25 @@ public class PortalController : ControllerBase
|
||||
private readonly QuotaHelper _quotaHelper;
|
||||
private readonly IEventBus _eventBus;
|
||||
|
||||
public PortalController(
|
||||
ILogger<PortalController> logger,
|
||||
ApiContext apiContext,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
ITariffService tariffService,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
UrlShortener urlShortener,
|
||||
AuthContext authContext,
|
||||
WebItemSecurity webItemSecurity,
|
||||
SecurityContext securityContext,
|
||||
SettingsManager settingsManager,
|
||||
IMobileAppInstallRegistrator mobileAppInstallRegistrator,
|
||||
TenantExtra tenantExtra,
|
||||
IConfiguration configuration,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
LicenseReader licenseReader,
|
||||
SetupInfo setupInfo,
|
||||
DocumentServiceLicense documentServiceLicense,
|
||||
public PortalController(
|
||||
ILogger<PortalController> logger,
|
||||
ApiContext apiContext,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
ITariffService tariffService,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
IUrlShortener urlShortener,
|
||||
AuthContext authContext,
|
||||
WebItemSecurity webItemSecurity,
|
||||
SecurityContext securityContext,
|
||||
SettingsManager settingsManager,
|
||||
IMobileAppInstallRegistrator mobileAppInstallRegistrator,
|
||||
TenantExtra tenantExtra,
|
||||
IConfiguration configuration,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
LicenseReader licenseReader,
|
||||
SetupInfo setupInfo,
|
||||
DocumentServiceLicense documentServiceLicense,
|
||||
IHttpClientFactory clientFactory,
|
||||
ApiSystemHelper apiSystemHelper,
|
||||
CoreSettings coreSettings,
|
||||
@ -101,25 +101,25 @@ public class PortalController : ControllerBase
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
QuotaHelper quotaHelper,
|
||||
IEventBus eventBus)
|
||||
{
|
||||
_log = logger;
|
||||
_apiContext = apiContext;
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
_tariffService = tariffService;
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_urlShortener = urlShortener;
|
||||
_authContext = authContext;
|
||||
_webItemSecurity = webItemSecurity;
|
||||
_securityContext = securityContext;
|
||||
_settingsManager = settingsManager;
|
||||
_mobileAppInstallRegistrator = mobileAppInstallRegistrator;
|
||||
_configuration = configuration;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_licenseReader = licenseReader;
|
||||
_setupInfo = setupInfo;
|
||||
_documentServiceLicense = documentServiceLicense;
|
||||
_tenantExtra = tenantExtra;
|
||||
{
|
||||
_log = logger;
|
||||
_apiContext = apiContext;
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
_tariffService = tariffService;
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_urlShortener = urlShortener;
|
||||
_authContext = authContext;
|
||||
_webItemSecurity = webItemSecurity;
|
||||
_securityContext = securityContext;
|
||||
_settingsManager = settingsManager;
|
||||
_mobileAppInstallRegistrator = mobileAppInstallRegistrator;
|
||||
_configuration = configuration;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_licenseReader = licenseReader;
|
||||
_setupInfo = setupInfo;
|
||||
_documentServiceLicense = documentServiceLicense;
|
||||
_tenantExtra = tenantExtra;
|
||||
_clientFactory = clientFactory;
|
||||
_apiSystemHelper = apiSystemHelper;
|
||||
_coreSettings = coreSettings;
|
||||
@ -135,61 +135,61 @@ public class PortalController : ControllerBase
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_quotaHelper = quotaHelper;
|
||||
_eventBus = eventBus;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpGet("")]
|
||||
public TenantDto Get()
|
||||
{
|
||||
return _mapper.Map<TenantDto>(Tenant);
|
||||
}
|
||||
|
||||
[HttpGet("users/{userID}")]
|
||||
[HttpGet("")]
|
||||
public TenantDto Get()
|
||||
{
|
||||
return _mapper.Map<TenantDto>(Tenant);
|
||||
}
|
||||
|
||||
[HttpGet("users/{userID}")]
|
||||
public async Task<UserInfo> GetUserAsync(Guid userID)
|
||||
{
|
||||
{
|
||||
return await _userManager.GetUsersAsync(userID);
|
||||
}
|
||||
|
||||
[HttpGet("users/invite/{employeeType}")]
|
||||
}
|
||||
|
||||
[HttpGet("users/invite/{employeeType}")]
|
||||
public async Task<object> GeInviteLinkAsync(EmployeeType employeeType)
|
||||
{
|
||||
{
|
||||
if (!await _permissionContext.CheckPermissionsAsync(new UserSecurityProvider(Guid.Empty, employeeType), ASC.Core.Users.Constants.Action_AddRemoveUser))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return await _commonLinkUtility.GetConfirmationEmailUrlAsync(string.Empty, ConfirmType.LinkInvite, (int)employeeType, _authContext.CurrentAccount.ID)
|
||||
+ $"&emplType={employeeType:d}";
|
||||
}
|
||||
|
||||
[HttpPut("getshortenlink")]
|
||||
public async Task<object> GetShortenLinkAsync(ShortenLinkRequestsDto inDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _urlShortener.Instance.GetShortenLinkAsync(inDto.Link);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.ErrorGetShortenLink(ex);
|
||||
return inDto.Link;
|
||||
}
|
||||
}
|
||||
|
||||
+ $"&emplType={employeeType:d}";
|
||||
}
|
||||
|
||||
[HttpPut("getshortenlink")]
|
||||
public async Task<object> GetShortenLinkAsync(ShortenLinkRequestsDto inDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _urlShortener.GetShortenLinkAsync(inDto.Link);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.ErrorGetShortenLink(ex);
|
||||
return inDto.Link;
|
||||
}
|
||||
}
|
||||
|
||||
[AllowNotPayment, AllowAnonymous]
|
||||
[HttpGet("tenantextra")]
|
||||
[HttpGet("tenantextra")]
|
||||
public async Task<TenantExtraDto> GetTenantExtra(bool refresh)
|
||||
{
|
||||
{
|
||||
var result = new TenantExtraDto
|
||||
{
|
||||
{
|
||||
CustomMode = _coreBaseSettings.CustomMode,
|
||||
Opensource = _tenantExtra.Opensource,
|
||||
Enterprise = _tenantExtra.Enterprise,
|
||||
EnableTariffPage = //TenantExtra.EnableTarrifSettings - think about hide-settings for opensource
|
||||
(!_coreBaseSettings.Standalone || !string.IsNullOrEmpty(_licenseReader.LicensePath))
|
||||
&& string.IsNullOrEmpty(_setupInfo.AmiMetaUrl)
|
||||
(!_coreBaseSettings.Standalone || !string.IsNullOrEmpty(_licenseReader.LicensePath))
|
||||
&& string.IsNullOrEmpty(_setupInfo.AmiMetaUrl)
|
||||
&& !_coreBaseSettings.CustomMode
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -201,120 +201,120 @@ public class PortalController : ControllerBase
|
||||
result.LicenseAccept = _settingsManager.LoadForDefaultTenant<TariffSettings>().LicenseAcceptSetting;
|
||||
result.DocServerUserQuota = await _documentServiceLicense.GetLicenseQuotaAsync();
|
||||
result.DocServerLicense = await _documentServiceLicense.GetLicenseAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("usedspace")]
|
||||
[HttpGet("usedspace")]
|
||||
public async Task<double> GetUsedSpaceAsync()
|
||||
{
|
||||
return Math.Round(
|
||||
{
|
||||
return Math.Round(
|
||||
(await _tenantManager.FindTenantQuotaRowsAsync(Tenant.Id))
|
||||
.Where(q => !string.IsNullOrEmpty(q.Tag) && new Guid(q.Tag) != Guid.Empty)
|
||||
.Sum(q => q.Counter) / 1024f / 1024f / 1024f, 2);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("userscount")]
|
||||
.Where(q => !string.IsNullOrEmpty(q.Tag) && new Guid(q.Tag) != Guid.Empty)
|
||||
.Sum(q => q.Counter) / 1024f / 1024f / 1024f, 2);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("userscount")]
|
||||
public async Task<long> GetUsersCountAsync()
|
||||
{
|
||||
{
|
||||
return _coreBaseSettings.Personal ? 1 : (await _userManager.GetUserNamesAsync(EmployeeStatus.Active)).Length;
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpGet("tariff")]
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpGet("tariff")]
|
||||
public async Task<Tariff> GetTariffAsync(bool refresh)
|
||||
{
|
||||
{
|
||||
return await _tariffService.GetTariffAsync(Tenant.Id, refresh: refresh);
|
||||
}
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpGet("quota")]
|
||||
[AllowNotPayment]
|
||||
[HttpGet("quota")]
|
||||
public async Task<TenantQuota> GetQuotaAsync()
|
||||
{
|
||||
{
|
||||
return await _tenantManager.GetTenantQuotaAsync(Tenant.Id);
|
||||
}
|
||||
|
||||
[HttpGet("quota/right")]
|
||||
}
|
||||
|
||||
[HttpGet("quota/right")]
|
||||
public async Task<TenantQuota> GetRightQuotaAsync()
|
||||
{
|
||||
{
|
||||
var usedSpace = await GetUsedSpaceAsync();
|
||||
var needUsersCount = await GetUsersCountAsync();
|
||||
|
||||
|
||||
return (await _tenantManager.GetTenantQuotasAsync()).OrderBy(r => r.Price)
|
||||
.FirstOrDefault(quota =>
|
||||
quota.CountUser > needUsersCount
|
||||
&& quota.MaxTotalSize > usedSpace);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("path")]
|
||||
public object GetFullAbsolutePath(string virtualPath)
|
||||
{
|
||||
return _commonLinkUtility.GetFullAbsolutePath(virtualPath);
|
||||
}
|
||||
|
||||
[HttpGet("thumb")]
|
||||
public FileResult GetThumb(string url)
|
||||
{
|
||||
if (!_securityContext.IsAuthenticated || _configuration["bookmarking:thumbnail-url"] == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
url = url.Replace("&", "&");
|
||||
url = WebUtility.UrlEncode(url);
|
||||
|
||||
.FirstOrDefault(quota =>
|
||||
quota.CountUser > needUsersCount
|
||||
&& quota.MaxTotalSize > usedSpace);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("path")]
|
||||
public object GetFullAbsolutePath(string virtualPath)
|
||||
{
|
||||
return _commonLinkUtility.GetFullAbsolutePath(virtualPath);
|
||||
}
|
||||
|
||||
[HttpGet("thumb")]
|
||||
public FileResult GetThumb(string url)
|
||||
{
|
||||
if (!_securityContext.IsAuthenticated || _configuration["bookmarking:thumbnail-url"] == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
url = url.Replace("&", "&");
|
||||
url = WebUtility.UrlEncode(url);
|
||||
|
||||
var request = new HttpRequestMessage
|
||||
{
|
||||
RequestUri = new Uri(string.Format(_configuration["bookmarking:thumbnail-url"], url))
|
||||
};
|
||||
|
||||
var httpClient = _clientFactory.CreateClient();
|
||||
using var response = httpClient.Send(request);
|
||||
using var stream = response.Content.ReadAsStream();
|
||||
var bytes = new byte[stream.Length];
|
||||
stream.Read(bytes, 0, (int)stream.Length);
|
||||
|
||||
string type;
|
||||
if (response.Headers.TryGetValues("Content-Type", out var values))
|
||||
{
|
||||
type = values.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "image/png";
|
||||
}
|
||||
return File(bytes, type);
|
||||
}
|
||||
|
||||
[HttpPost("present/mark")]
|
||||
};
|
||||
|
||||
var httpClient = _clientFactory.CreateClient();
|
||||
using var response = httpClient.Send(request);
|
||||
using var stream = response.Content.ReadAsStream();
|
||||
var bytes = new byte[stream.Length];
|
||||
stream.Read(bytes, 0, (int)stream.Length);
|
||||
|
||||
string type;
|
||||
if (response.Headers.TryGetValues("Content-Type", out var values))
|
||||
{
|
||||
type = values.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "image/png";
|
||||
}
|
||||
return File(bytes, type);
|
||||
}
|
||||
|
||||
[HttpPost("present/mark")]
|
||||
public async Task MarkPresentAsReadedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = await _settingsManager.LoadForCurrentUserAsync<OpensourceGiftSettings>();
|
||||
settings.Readed = true;
|
||||
settings.Readed = true;
|
||||
await _settingsManager.SaveForCurrentUserAsync(settings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.ErrorMarkPresentAsReaded(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("mobile/registration")]
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.ErrorMarkPresentAsReaded(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("mobile/registration")]
|
||||
public async Task RegisterMobileAppInstallAsync(MobileAppRequestsDto inDto)
|
||||
{
|
||||
{
|
||||
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
||||
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, inDto.Type);
|
||||
}
|
||||
|
||||
[HttpPost("mobile/registration")]
|
||||
}
|
||||
|
||||
[HttpPost("mobile/registration")]
|
||||
public async Task RegisterMobileAppInstallAsync(MobileAppType type)
|
||||
{
|
||||
{
|
||||
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
||||
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, type);
|
||||
}
|
||||
@ -576,5 +576,5 @@ public class PortalController : ControllerBase
|
||||
default:
|
||||
throw new SecurityException("Access Denied.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,12 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.Controllers.Settings;
|
||||
namespace ASC.Web.Api.Controllers.Settings;
|
||||
|
||||
public class SettingsController : BaseSettingsController
|
||||
{
|
||||
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
|
||||
private Tenant Tenant { get { return ApiContext.Tenant; } }
|
||||
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
|
||||
private Tenant Tenant { get { return ApiContext.Tenant; } }
|
||||
|
||||
private readonly MessageService _messageService;
|
||||
private readonly ConsumerFactory _consumerFactory;
|
||||
@ -51,18 +51,17 @@ public class SettingsController : BaseSettingsController
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly StatisticManager _statisticManager;
|
||||
private readonly UrlShortener _urlShortener;
|
||||
private readonly PasswordHasher _passwordHasher;
|
||||
private readonly ILogger _log;
|
||||
private readonly TelegramHelper _telegramHelper;
|
||||
private readonly DnsSettings _dnsSettings;
|
||||
private readonly AdditionalWhiteLabelSettingsHelperInit _additionalWhiteLabelSettingsHelper;
|
||||
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
|
||||
private readonly QuotaUsageManager _quotaUsageManager;
|
||||
private readonly TenantDomainValidator _tenantDomainValidator;
|
||||
private readonly TelegramHelper _telegramHelper;
|
||||
private readonly DnsSettings _dnsSettings;
|
||||
private readonly AdditionalWhiteLabelSettingsHelperInit _additionalWhiteLabelSettingsHelper;
|
||||
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
|
||||
private readonly QuotaUsageManager _quotaUsageManager;
|
||||
private readonly TenantDomainValidator _tenantDomainValidator;
|
||||
private readonly QuotaSyncOperation _quotaSyncOperation;
|
||||
private readonly ExternalShare _externalShare;
|
||||
|
||||
private readonly ExternalShare _externalShare;
|
||||
|
||||
public SettingsController(
|
||||
ILoggerProvider option,
|
||||
MessageService messageService,
|
||||
@ -89,16 +88,15 @@ public class SettingsController : BaseSettingsController
|
||||
ProviderManager providerManager,
|
||||
FirstTimeTenantSettings firstTimeTenantSettings,
|
||||
TelegramHelper telegramHelper,
|
||||
UrlShortener urlShortener,
|
||||
PasswordHasher passwordHasher,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
DnsSettings dnsSettings,
|
||||
AdditionalWhiteLabelSettingsHelperInit additionalWhiteLabelSettingsHelper,
|
||||
PasswordHasher passwordHasher,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
DnsSettings dnsSettings,
|
||||
AdditionalWhiteLabelSettingsHelperInit additionalWhiteLabelSettingsHelper,
|
||||
CustomColorThemesSettingsHelper customColorThemesSettingsHelper,
|
||||
QuotaSyncOperation quotaSyncOperation,
|
||||
QuotaUsageManager quotaUsageManager,
|
||||
TenantDomainValidator tenantDomainValidator,
|
||||
ExternalShare externalShare
|
||||
QuotaUsageManager quotaUsageManager,
|
||||
TenantDomainValidator tenantDomainValidator,
|
||||
ExternalShare externalShare
|
||||
) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
|
||||
{
|
||||
_log = option.CreateLogger("ASC.Api");
|
||||
@ -106,7 +104,7 @@ public class SettingsController : BaseSettingsController
|
||||
_timeZoneConverter = timeZoneConverter;
|
||||
_customNamingPeople = customNamingPeople;
|
||||
_providerManager = providerManager;
|
||||
_firstTimeTenantSettings = firstTimeTenantSettings;
|
||||
_firstTimeTenantSettings = firstTimeTenantSettings;
|
||||
_messageService = messageService;
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
@ -123,45 +121,44 @@ public class SettingsController : BaseSettingsController
|
||||
_setupInfo = setupInfo;
|
||||
_statisticManager = statisticManager;
|
||||
_passwordHasher = passwordHasher;
|
||||
_urlShortener = urlShortener;
|
||||
_telegramHelper = telegramHelper;
|
||||
_dnsSettings = dnsSettings;
|
||||
_additionalWhiteLabelSettingsHelper = additionalWhiteLabelSettingsHelper;
|
||||
_telegramHelper = telegramHelper;
|
||||
_dnsSettings = dnsSettings;
|
||||
_additionalWhiteLabelSettingsHelper = additionalWhiteLabelSettingsHelper;
|
||||
_quotaSyncOperation = quotaSyncOperation;
|
||||
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
|
||||
_quotaUsageManager = quotaUsageManager;
|
||||
_tenantDomainValidator = tenantDomainValidator;
|
||||
_externalShare = externalShare;
|
||||
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
|
||||
_quotaUsageManager = quotaUsageManager;
|
||||
_tenantDomainValidator = tenantDomainValidator;
|
||||
_externalShare = externalShare;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
[HttpGet("")]
|
||||
[AllowNotPayment, AllowSuspended, AllowAnonymous]
|
||||
public async Task<SettingsDto> GetSettingsAsync(bool? withpassword)
|
||||
{
|
||||
var studioAdminMessageSettings = await _settingsManager.LoadAsync<StudioAdminMessageSettings>();
|
||||
var tenantCookieSettings = _settingsManager.Load<TenantCookieSettings>();
|
||||
public async Task<SettingsDto> GetSettingsAsync(bool? withpassword)
|
||||
{
|
||||
var studioAdminMessageSettings = await _settingsManager.LoadAsync<StudioAdminMessageSettings>();
|
||||
var tenantCookieSettings = _settingsManager.Load<TenantCookieSettings>();
|
||||
|
||||
var settings = new SettingsDto
|
||||
{
|
||||
Culture = Tenant.GetCulture().ToString(),
|
||||
GreetingSettings = Tenant.Name == "" ? Resource.PortalName : Tenant.Name,
|
||||
Personal = _coreBaseSettings.Personal,
|
||||
DocSpace = !_coreBaseSettings.DisableDocSpace,
|
||||
Personal = _coreBaseSettings.Personal,
|
||||
DocSpace = !_coreBaseSettings.DisableDocSpace,
|
||||
Standalone = _coreBaseSettings.Standalone,
|
||||
BaseDomain = _coreBaseSettings.Basedomain,
|
||||
Version = _configuration["version:number"] ?? "",
|
||||
TenantStatus = (await _tenantManager.GetCurrentTenantAsync()).Status,
|
||||
TenantAlias = Tenant.Alias,
|
||||
EnableAdmMess = studioAdminMessageSettings.Enable || await _tenantExtra.IsNotPaidAsync(),
|
||||
LegalTerms = _setupInfo.LegalTerms,
|
||||
CookieSettingsEnabled = tenantCookieSettings.Enabled
|
||||
BaseDomain = _coreBaseSettings.Basedomain,
|
||||
Version = _configuration["version:number"] ?? "",
|
||||
TenantStatus = (await _tenantManager.GetCurrentTenantAsync()).Status,
|
||||
TenantAlias = Tenant.Alias,
|
||||
EnableAdmMess = studioAdminMessageSettings.Enable || await _tenantExtra.IsNotPaidAsync(),
|
||||
LegalTerms = _setupInfo.LegalTerms,
|
||||
CookieSettingsEnabled = tenantCookieSettings.Enabled
|
||||
};
|
||||
|
||||
if (!_authContext.IsAuthenticated && await _externalShare.GetLinkIdAsync() != default)
|
||||
{
|
||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||
}
|
||||
|
||||
if (!_authContext.IsAuthenticated && await _externalShare.GetLinkIdAsync() != default)
|
||||
{
|
||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||
}
|
||||
|
||||
if (_authContext.IsAuthenticated)
|
||||
{
|
||||
settings.TrustedDomains = Tenant.TrustedDomains;
|
||||
@ -172,11 +169,11 @@ public class SettingsController : BaseSettingsController
|
||||
settings.UtcHoursOffset = settings.UtcOffset.TotalHours;
|
||||
settings.OwnerId = Tenant.OwnerId;
|
||||
settings.NameSchemaId = _customNamingPeople.Current.Id;
|
||||
settings.DomainValidator = _tenantDomainValidator;
|
||||
settings.ZendeskKey = _setupInfo.ZendeskKey;
|
||||
settings.BookTrainingEmail = _setupInfo.BookTrainingEmail;
|
||||
settings.DocumentationEmail = _setupInfo.DocumentationEmail;
|
||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||
settings.DomainValidator = _tenantDomainValidator;
|
||||
settings.ZendeskKey = _setupInfo.ZendeskKey;
|
||||
settings.BookTrainingEmail = _setupInfo.BookTrainingEmail;
|
||||
settings.DocumentationEmail = _setupInfo.DocumentationEmail;
|
||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||
|
||||
settings.Firebase = new FirebaseDto
|
||||
{
|
||||
@ -186,32 +183,32 @@ public class SettingsController : BaseSettingsController
|
||||
StorageBucket = _configuration["firebase:storageBucket"] ?? "",
|
||||
MessagingSenderId = _configuration["firebase:messagingSenderId"] ?? "",
|
||||
AppId = _configuration["firebase:appId"] ?? "",
|
||||
MeasurementId = _configuration["firebase:measurementId"] ?? "",
|
||||
DatabaseURL = _configuration["firebase:databaseURL"] ?? ""
|
||||
};
|
||||
|
||||
settings.HelpLink = await _commonLinkUtility.GetHelpLinkAsync(_settingsManager, _additionalWhiteLabelSettingsHelper, true);
|
||||
settings.ApiDocsLink = _configuration["web:api-docs"];
|
||||
MeasurementId = _configuration["firebase:measurementId"] ?? "",
|
||||
DatabaseURL = _configuration["firebase:databaseURL"] ?? ""
|
||||
};
|
||||
|
||||
settings.HelpLink = await _commonLinkUtility.GetHelpLinkAsync(_settingsManager, _additionalWhiteLabelSettingsHelper, true);
|
||||
settings.ApiDocsLink = _configuration["web:api-docs"];
|
||||
|
||||
bool debugInfo;
|
||||
if (bool.TryParse(_configuration["debug-info:enabled"], out debugInfo))
|
||||
{
|
||||
settings.DebugInfo = debugInfo;
|
||||
}
|
||||
|
||||
settings.Plugins = new PluginsDto();
|
||||
|
||||
bool pluginsEnabled;
|
||||
if (bool.TryParse(_configuration["plugins:enabled"], out pluginsEnabled))
|
||||
{
|
||||
settings.Plugins.Enabled = pluginsEnabled;
|
||||
}
|
||||
|
||||
settings.Plugins.Allow = _configuration.GetSection("plugins:allow").Get<List<string>>() ?? new List<string>();
|
||||
}
|
||||
|
||||
settings.Plugins = new PluginsDto();
|
||||
|
||||
bool pluginsEnabled;
|
||||
if (bool.TryParse(_configuration["plugins:enabled"], out pluginsEnabled))
|
||||
{
|
||||
settings.Plugins.Enabled = pluginsEnabled;
|
||||
}
|
||||
|
||||
settings.Plugins.Allow = _configuration.GetSection("plugins:allow").Get<List<string>>() ?? new List<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(await _settingsManager.LoadAsync<WizardSettings>()).Completed)
|
||||
if (!(await _settingsManager.LoadAsync<WizardSettings>()).Completed)
|
||||
{
|
||||
settings.WizardToken = _commonLinkUtility.GetToken(Tenant.Id, "", ConfirmType.Wizard, userId: Tenant.OwnerId);
|
||||
}
|
||||
@ -241,13 +238,13 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[HttpPost("maildomainsettings")]
|
||||
public async Task<object> SaveMailDomainSettingsAsync(MailDomainSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
public async Task<object> SaveMailDomainSettingsAsync(MailDomainSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
if (inDto.Type == TenantTrustedDomainsType.Custom)
|
||||
{
|
||||
Tenant.TrustedDomainsRaw = "";
|
||||
Tenant.TrustedDomainsRaw = "";
|
||||
Tenant.TrustedDomains.Clear();
|
||||
foreach (var d in inDto.Domains.Select(domain => (domain ?? "").Trim().ToLower()))
|
||||
{
|
||||
@ -267,11 +264,11 @@ public class SettingsController : BaseSettingsController
|
||||
|
||||
Tenant.TrustedDomainsType = inDto.Type;
|
||||
|
||||
await _settingsManager.SaveAsync(new StudioTrustedDomainSettings { InviteAsUsers = inDto.InviteAsUsers });
|
||||
await _settingsManager.SaveAsync(new StudioTrustedDomainSettings { InviteAsUsers = inDto.InviteAsUsers });
|
||||
|
||||
await _tenantManager.SaveTenantAsync(Tenant);
|
||||
await _tenantManager.SaveTenantAsync(Tenant);
|
||||
|
||||
await _messageService.SendAsync(MessageAction.TrustedMailDomainSettingsUpdated);
|
||||
await _messageService.SendAsync(MessageAction.TrustedMailDomainSettingsUpdated);
|
||||
|
||||
return Resource.SuccessfullySaveSettingsMessage;
|
||||
}
|
||||
@ -283,16 +280,16 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[HttpPost("userquotasettings")]
|
||||
public async Task<object> SaveUserQuotaSettingsAsync(UserQuotaSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
public async Task<object> SaveUserQuotaSettingsAsync(UserQuotaSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
await _settingsManager.SaveAsync(new TenantUserQuotaSettings { EnableUserQuota = inDto.EnableUserQuota, DefaultUserQuota = inDto.DefaultUserQuota });
|
||||
await _settingsManager.SaveAsync(new TenantUserQuotaSettings { EnableUserQuota = inDto.EnableUserQuota, DefaultUserQuota = inDto.DefaultUserQuota });
|
||||
|
||||
return Resource.SuccessfullySaveSettingsMessage;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[AllowAnonymous]
|
||||
[AllowNotPayment]
|
||||
[HttpGet("cultures")]
|
||||
public IEnumerable<object> GetSupportedCultures()
|
||||
@ -301,11 +298,11 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard,Administrators")]
|
||||
[HttpGet("timezones")]
|
||||
[HttpGet("timezones")]
|
||||
[AllowNotPayment]
|
||||
public async Task<List<TimezonesRequestsDto>> GetTimeZonesAsyncAsync()
|
||||
public async Task<List<TimezonesRequestsDto>> GetTimeZonesAsyncAsync()
|
||||
{
|
||||
await ApiContext.AuthByClaimAsync();
|
||||
await ApiContext.AuthByClaimAsync();
|
||||
var timeZones = TimeZoneInfo.GetSystemTimeZones().ToList();
|
||||
|
||||
if (timeZones.All(tz => tz.Id != "UTC"))
|
||||
@ -328,193 +325,193 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
||||
[HttpGet("machine")]
|
||||
[HttpGet("machine")]
|
||||
[AllowNotPayment]
|
||||
public object GetMachineName()
|
||||
{
|
||||
return Dns.GetHostName().ToLowerInvariant();
|
||||
}
|
||||
|
||||
[HttpPut("dns")]
|
||||
public async Task<object> SaveDnsSettingsAsync(DnsSettingsRequestsDto model)
|
||||
{
|
||||
return await _dnsSettings.SaveDnsSettingsAsync(model.DnsName, model.Enable);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("dns")]
|
||||
public async Task<object> SaveDnsSettingsAsync(DnsSettingsRequestsDto model)
|
||||
{
|
||||
return await _dnsSettings.SaveDnsSettingsAsync(model.DnsName, model.Enable);
|
||||
}
|
||||
|
||||
[HttpGet("recalculatequota")]
|
||||
public async Task RecalculateQuotaAsync()
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
_quotaSyncOperation.RecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||
public async Task RecalculateQuotaAsync()
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
_quotaSyncOperation.RecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||
}
|
||||
|
||||
[HttpGet("checkrecalculatequota")]
|
||||
public async Task<bool> CheckRecalculateQuotaAsync()
|
||||
public async Task<bool> CheckRecalculateQuotaAsync()
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
return _quotaSyncOperation.CheckRecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
return _quotaSyncOperation.CheckRecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||
}
|
||||
|
||||
[HttpGet("logo")]
|
||||
public async Task<object> GetLogoAsync()
|
||||
public async Task<object> GetLogoAsync()
|
||||
{
|
||||
return await _tenantInfoSettingsHelper.GetAbsoluteCompanyLogoPathAsync(await _settingsManager.LoadAsync<TenantInfoSettings>());
|
||||
return await _tenantInfoSettingsHelper.GetAbsoluteCompanyLogoPathAsync(await _settingsManager.LoadAsync<TenantInfoSettings>());
|
||||
}
|
||||
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpPut("wizard/complete")]
|
||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
||||
public async Task<WizardSettings> CompleteWizardAsync(WizardRequestsDto inDto)
|
||||
{
|
||||
await ApiContext.AuthByClaimAsync();
|
||||
public async Task<WizardSettings> CompleteWizardAsync(WizardRequestsDto inDto)
|
||||
{
|
||||
await ApiContext.AuthByClaimAsync();
|
||||
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
return await _firstTimeTenantSettings.SaveDataAsync(inDto);
|
||||
return await _firstTimeTenantSettings.SaveDataAsync(inDto);
|
||||
}
|
||||
|
||||
///<visible>false</visible>
|
||||
[HttpPut("welcome/close")]
|
||||
public async Task CloseWelcomePopupAsync()
|
||||
public async Task CloseWelcomePopupAsync()
|
||||
{
|
||||
var currentUser = await _userManager.GetUsersAsync(_authContext.CurrentAccount.ID);
|
||||
var currentUser = await _userManager.GetUsersAsync(_authContext.CurrentAccount.ID);
|
||||
|
||||
var collaboratorPopupSettings = await _settingsManager.LoadForCurrentUserAsync<CollaboratorSettings>();
|
||||
var collaboratorPopupSettings = await _settingsManager.LoadForCurrentUserAsync<CollaboratorSettings>();
|
||||
|
||||
if (!(await _userManager.IsUserAsync(currentUser) && collaboratorPopupSettings.FirstVisit && !await _userManager.IsOutsiderAsync(currentUser)))
|
||||
if (!(await _userManager.IsUserAsync(currentUser) && collaboratorPopupSettings.FirstVisit && !await _userManager.IsOutsiderAsync(currentUser)))
|
||||
{
|
||||
throw new NotSupportedException("Not available.");
|
||||
}
|
||||
|
||||
collaboratorPopupSettings.FirstVisit = false;
|
||||
await _settingsManager.SaveForCurrentUserAsync(collaboratorPopupSettings);
|
||||
await _settingsManager.SaveForCurrentUserAsync(collaboratorPopupSettings);
|
||||
}
|
||||
|
||||
[AllowAnonymous, AllowNotPayment, AllowSuspended]
|
||||
[HttpGet("colortheme")]
|
||||
public async Task<CustomColorThemesSettingsDto> GetColorThemeAsync()
|
||||
{
|
||||
return new CustomColorThemesSettingsDto(await _settingsManager.LoadAsync<CustomColorThemesSettings>(), _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
public async Task<CustomColorThemesSettingsDto> GetColorThemeAsync()
|
||||
{
|
||||
return new CustomColorThemesSettingsDto(await _settingsManager.LoadAsync<CustomColorThemesSettings>(), _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
|
||||
[HttpPut("colortheme")]
|
||||
public async Task<CustomColorThemesSettingsDto> SaveColorThemeAsync(CustomColorThemesSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||
|
||||
if (inDto.Theme != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _semaphore.WaitAsync();
|
||||
var theme = inDto.Theme;
|
||||
|
||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == theme.Id))
|
||||
{
|
||||
theme.Id = 0;
|
||||
}
|
||||
|
||||
var settingItem = settings.Themes.SingleOrDefault(r => r.Id == theme.Id);
|
||||
if (settingItem != null)
|
||||
{
|
||||
if (theme.Main != null)
|
||||
{
|
||||
settingItem.Main = new CustomColorThemesSettingsColorItem
|
||||
{
|
||||
Accent = theme.Main.Accent,
|
||||
Buttons = theme.Main.Buttons
|
||||
};
|
||||
}
|
||||
if (theme.Text != null)
|
||||
{
|
||||
settingItem.Text = new CustomColorThemesSettingsColorItem
|
||||
{
|
||||
Accent = theme.Text.Accent,
|
||||
Buttons = theme.Text.Buttons
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_customColorThemesSettingsHelper.Limit == 0 || settings.Themes.Count < _customColorThemesSettingsHelper.Limit)
|
||||
{
|
||||
if (theme.Id == 0)
|
||||
{
|
||||
theme.Id = settings.Themes.Max(r => r.Id) + 1;
|
||||
}
|
||||
|
||||
theme.Name = "";
|
||||
settings.Themes = settings.Themes.Append(theme).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
if (inDto.Selected.HasValue && settings.Themes.Any(r => r.Id == inDto.Selected.Value))
|
||||
{
|
||||
settings.Selected = inDto.Selected.Value;
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||
}
|
||||
|
||||
public async Task<CustomColorThemesSettingsDto> SaveColorThemeAsync(CustomColorThemesSettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||
|
||||
if (inDto.Theme != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _semaphore.WaitAsync();
|
||||
var theme = inDto.Theme;
|
||||
|
||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == theme.Id))
|
||||
{
|
||||
theme.Id = 0;
|
||||
}
|
||||
|
||||
var settingItem = settings.Themes.SingleOrDefault(r => r.Id == theme.Id);
|
||||
if (settingItem != null)
|
||||
{
|
||||
if (theme.Main != null)
|
||||
{
|
||||
settingItem.Main = new CustomColorThemesSettingsColorItem
|
||||
{
|
||||
Accent = theme.Main.Accent,
|
||||
Buttons = theme.Main.Buttons
|
||||
};
|
||||
}
|
||||
if (theme.Text != null)
|
||||
{
|
||||
settingItem.Text = new CustomColorThemesSettingsColorItem
|
||||
{
|
||||
Accent = theme.Text.Accent,
|
||||
Buttons = theme.Text.Buttons
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_customColorThemesSettingsHelper.Limit == 0 || settings.Themes.Count < _customColorThemesSettingsHelper.Limit)
|
||||
{
|
||||
if (theme.Id == 0)
|
||||
{
|
||||
theme.Id = settings.Themes.Max(r => r.Id) + 1;
|
||||
}
|
||||
|
||||
theme.Name = "";
|
||||
settings.Themes = settings.Themes.Append(theme).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
if (inDto.Selected.HasValue && settings.Themes.Any(r => r.Id == inDto.Selected.Value))
|
||||
{
|
||||
settings.Selected = inDto.Selected.Value;
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||
}
|
||||
|
||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpDelete("colortheme")]
|
||||
public async Task<CustomColorThemesSettingsDto> DeleteColorThemeAsync(int id)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||
|
||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == id))
|
||||
{
|
||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
|
||||
settings.Themes = settings.Themes.Where(r => r.Id != id).ToList();
|
||||
|
||||
if (settings.Selected == id)
|
||||
{
|
||||
settings.Selected = settings.Themes.Min(r => r.Id);
|
||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||
}
|
||||
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
|
||||
public async Task<CustomColorThemesSettingsDto> DeleteColorThemeAsync(int id)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||
|
||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == id))
|
||||
{
|
||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
|
||||
settings.Themes = settings.Themes.Where(r => r.Id != id).ToList();
|
||||
|
||||
if (settings.Selected == id)
|
||||
{
|
||||
settings.Selected = settings.Themes.Min(r => r.Id);
|
||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||
}
|
||||
|
||||
await _settingsManager.SaveAsync(settings);
|
||||
|
||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||
}
|
||||
|
||||
[HttpPut("closeadminhelper")]
|
||||
public async Task CloseAdminHelperAsync()
|
||||
{
|
||||
if (!await _userManager.IsDocSpaceAdminAsync(_authContext.CurrentAccount.ID) || _coreBaseSettings.CustomMode || !_coreBaseSettings.Standalone)
|
||||
{
|
||||
throw new NotSupportedException("Not available.");
|
||||
}
|
||||
|
||||
var adminHelperSettings = await _settingsManager.LoadForCurrentUserAsync<AdminHelperSettings>();
|
||||
adminHelperSettings.Viewed = true;
|
||||
await _settingsManager.SaveForCurrentUserAsync(adminHelperSettings);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("closeadminhelper")]
|
||||
public async Task CloseAdminHelperAsync()
|
||||
{
|
||||
if (!await _userManager.IsDocSpaceAdminAsync(_authContext.CurrentAccount.ID) || _coreBaseSettings.CustomMode || !_coreBaseSettings.Standalone)
|
||||
{
|
||||
throw new NotSupportedException("Not available.");
|
||||
}
|
||||
|
||||
var adminHelperSettings = await _settingsManager.LoadForCurrentUserAsync<AdminHelperSettings>();
|
||||
adminHelperSettings.Viewed = true;
|
||||
await _settingsManager.SaveForCurrentUserAsync(adminHelperSettings);
|
||||
}
|
||||
|
||||
///<visible>false</visible>
|
||||
[HttpPut("timeandlanguage")]
|
||||
public async Task<object> TimaAndLanguageAsync(SettingsRequestsDto inDto)
|
||||
public async Task<object> TimaAndLanguageAsync(SettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var culture = CultureInfo.GetCultureInfo(inDto.Lng);
|
||||
|
||||
@ -536,47 +533,47 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
Tenant.TimeZone = timeZones.FirstOrDefault(tz => tz.Id == inDto.TimeZoneID)?.Id ?? TimeZoneInfo.Utc.Id;
|
||||
|
||||
await _tenantManager.SaveTenantAsync(Tenant);
|
||||
await _tenantManager.SaveTenantAsync(Tenant);
|
||||
|
||||
if (!Tenant.TimeZone.Equals(oldTimeZone) || changelng)
|
||||
{
|
||||
if (!Tenant.TimeZone.Equals(oldTimeZone))
|
||||
{
|
||||
await _messageService.SendAsync(MessageAction.TimeZoneSettingsUpdated);
|
||||
await _messageService.SendAsync(MessageAction.TimeZoneSettingsUpdated);
|
||||
}
|
||||
if (changelng)
|
||||
{
|
||||
await _messageService.SendAsync(MessageAction.LanguageSettingsUpdated);
|
||||
await _messageService.SendAsync(MessageAction.LanguageSettingsUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
return Resource.SuccessfullySaveSettingsMessage;
|
||||
}
|
||||
}
|
||||
|
||||
///<visible>false</visible>
|
||||
[HttpPut("defaultpage")]
|
||||
public async Task<object> SaveDefaultPageSettingAsync(SettingsRequestsDto inDto)
|
||||
public async Task<object> SaveDefaultPageSettingAsync(SettingsRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
await _settingsManager.SaveAsync(new StudioDefaultPageSettings { DefaultProductID = inDto.DefaultProductID });
|
||||
await _settingsManager.SaveAsync(new StudioDefaultPageSettings { DefaultProductID = inDto.DefaultProductID });
|
||||
|
||||
await _messageService.SendAsync(MessageAction.DefaultStartPageSettingsUpdated);
|
||||
await _messageService.SendAsync(MessageAction.DefaultStartPageSettingsUpdated);
|
||||
|
||||
return Resource.SuccessfullySaveSettingsMessage;
|
||||
}
|
||||
|
||||
[HttpPut("emailactivation")]
|
||||
public async Task<EmailActivationSettings> UpdateEmailActivationSettingsAsync(EmailActivationSettings settings)
|
||||
public async Task<EmailActivationSettings> UpdateEmailActivationSettingsAsync(EmailActivationSettings settings)
|
||||
{
|
||||
await _settingsManager.SaveForCurrentUserAsync(settings);
|
||||
await _settingsManager.SaveForCurrentUserAsync(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
[HttpGet("statistics/spaceusage/{id}")]
|
||||
public async Task<List<UsageSpaceStatItemDto>> GetSpaceUsageStatistics(Guid id)
|
||||
public async Task<List<UsageSpaceStatItemDto>> GetSpaceUsageStatistics(Guid id)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var webitem = _webItemManagerSecurity.GetItems(WebZoneType.All, ItemAvailableState.All)
|
||||
.FirstOrDefault(item =>
|
||||
@ -587,7 +584,7 @@ public class SettingsController : BaseSettingsController
|
||||
|
||||
if (webitem == null)
|
||||
{
|
||||
return new List<UsageSpaceStatItemDto>();
|
||||
return new List<UsageSpaceStatItemDto>();
|
||||
}
|
||||
|
||||
var statData = await webitem.Context.SpaceUsageStatManager.GetStatDataAsync();
|
||||
@ -603,9 +600,9 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[HttpGet("statistics/visit")]
|
||||
public async Task<List<ChartPointDto>> GetVisitStatisticsAsync(ApiDateTime fromDate, ApiDateTime toDate)
|
||||
public async Task<List<ChartPointDto>> GetVisitStatisticsAsync(ApiDateTime fromDate, ApiDateTime toDate)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var from = _tenantUtil.DateTimeFromUtc(fromDate);
|
||||
var to = _tenantUtil.DateTimeFromUtc(toDate);
|
||||
@ -628,8 +625,8 @@ public class SettingsController : BaseSettingsController
|
||||
});
|
||||
}
|
||||
|
||||
var hits = await _statisticManager.GetHitsByPeriodAsync(Tenant.Id, from, to);
|
||||
var hosts = await _statisticManager.GetHostsByPeriodAsync(Tenant.Id, from, to);
|
||||
var hits = await _statisticManager.GetHitsByPeriodAsync(Tenant.Id, from, to);
|
||||
var hosts = await _statisticManager.GetHostsByPeriodAsync(Tenant.Id, from, to);
|
||||
|
||||
if (hits.Count == 0 || hosts.Count == 0)
|
||||
{
|
||||
@ -689,11 +686,11 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
[HttpPost("authservice")]
|
||||
public async Task<bool> SaveAuthKeys(AuthServiceRequestsDto inDto)
|
||||
public async Task<bool> SaveAuthKeys(AuthServiceRequestsDto inDto)
|
||||
{
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
var saveAvailable = _coreBaseSettings.Standalone || (await _tenantManager.GetTenantQuotaAsync(await _tenantManager.GetCurrentTenantIdAsync())).ThirdParty;
|
||||
var saveAvailable = _coreBaseSettings.Standalone || (await _tenantManager.GetTenantQuotaAsync(await _tenantManager.GetCurrentTenantIdAsync())).ThirdParty;
|
||||
if (!SetupInfo.IsVisibleSettings(nameof(ManagementType.ThirdPartyAuthorization))
|
||||
|| !saveAvailable)
|
||||
{
|
||||
@ -701,25 +698,10 @@ public class SettingsController : BaseSettingsController
|
||||
}
|
||||
|
||||
var changed = false;
|
||||
var consumer = _consumerFactory.GetByKey<Consumer>(inDto.Name);
|
||||
|
||||
var consumer = _consumerFactory.GetByKey<Consumer>(inDto.Name);
|
||||
|
||||
var validateKeyProvider = consumer as IValidateKeysProvider;
|
||||
|
||||
if (validateKeyProvider != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (validateKeyProvider is BitlyLoginProvider bitly)
|
||||
{
|
||||
_urlShortener.Instance = null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.ErrorSaveAuthKeys(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (inDto.Props.All(r => string.IsNullOrEmpty(r.Value)))
|
||||
{
|
||||
consumer.Clear();
|
||||
@ -739,7 +721,7 @@ public class SettingsController : BaseSettingsController
|
||||
? consumer.ManagedKeys.All(key => string.IsNullOrEmpty(consumer[key]))
|
||||
: consumer.All(r => string.IsNullOrEmpty(r.Value));
|
||||
|
||||
if (validateKeyProvider != null && !await validateKeyProvider.ValidateKeysAsync() && !allPropsIsEmpty)
|
||||
if (validateKeyProvider != null && !await validateKeyProvider.ValidateKeysAsync() && !allPropsIsEmpty)
|
||||
{
|
||||
consumer.Clear();
|
||||
throw new ArgumentException(Resource.ErrorBadKeys);
|
||||
@ -747,24 +729,24 @@ public class SettingsController : BaseSettingsController
|
||||
|
||||
if (changed)
|
||||
{
|
||||
await _messageService.SendAsync(MessageAction.AuthorizationKeysSetting);
|
||||
await _messageService.SendAsync(MessageAction.AuthorizationKeysSetting);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
[HttpGet("payment")]
|
||||
public async Task<object> PaymentSettingsAsync()
|
||||
public async Task<object> PaymentSettingsAsync()
|
||||
{
|
||||
var settings = await _settingsManager.LoadForDefaultTenantAsync<AdditionalWhiteLabelSettings>();
|
||||
var currentQuota = await _tenantManager.GetCurrentTenantQuotaAsync();
|
||||
var currentTariff = await _tenantExtra.GetCurrentTariffAsync();
|
||||
var settings = await _settingsManager.LoadForDefaultTenantAsync<AdditionalWhiteLabelSettings>();
|
||||
var currentQuota = await _tenantManager.GetCurrentTenantQuotaAsync();
|
||||
var currentTariff = await _tenantExtra.GetCurrentTariffAsync();
|
||||
|
||||
if (!int.TryParse(_configuration["core:payment:max-quantity"], out var maxQuotaQuantity))
|
||||
{
|
||||
maxQuotaQuantity = 999;
|
||||
}
|
||||
if (!int.TryParse(_configuration["core:payment:max-quantity"], out var maxQuotaQuantity))
|
||||
{
|
||||
maxQuotaQuantity = 999;
|
||||
}
|
||||
|
||||
return
|
||||
new
|
||||
@ -777,7 +759,7 @@ public class SettingsController : BaseSettingsController
|
||||
{
|
||||
currentQuota.Trial,
|
||||
currentTariff.DueDate.Date
|
||||
},
|
||||
},
|
||||
max = maxQuotaQuantity
|
||||
};
|
||||
}
|
||||
@ -809,17 +791,17 @@ public class SettingsController : BaseSettingsController
|
||||
/// </summary>
|
||||
/// <returns>0 - not connected, 1 - connected, 2 - awaiting confirmation</returns>
|
||||
[HttpGet("telegramisconnected")]
|
||||
public async Task<object> TelegramIsConnectedAsync()
|
||||
public async Task<object> TelegramIsConnectedAsync()
|
||||
{
|
||||
return (int) await _telegramHelper.UserIsConnectedAsync(_authContext.CurrentAccount.ID, Tenant.Id);
|
||||
return (int) await _telegramHelper.UserIsConnectedAsync(_authContext.CurrentAccount.ID, Tenant.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlinks TelegramBot from your account
|
||||
/// </summary>
|
||||
[HttpDelete("telegramdisconnect")]
|
||||
public async Task TelegramDisconnectAsync()
|
||||
public async Task TelegramDisconnectAsync()
|
||||
{
|
||||
await _telegramHelper.DisconnectAsync(_authContext.CurrentAccount.ID, Tenant.Id);
|
||||
await _telegramHelper.DisconnectAsync(_authContext.CurrentAccount.ID, Tenant.Id);
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@ public class Startup : BaseStartup
|
||||
services.AddHostedService<LdapNotifyService>();
|
||||
DIHelper.TryAdd<LdapNotifyService>();
|
||||
}
|
||||
|
||||
services.AddBaseDbContextPool<FilesDbContext>();
|
||||
services.AddBaseDbContextPool<BackupsContext>();
|
||||
|
||||
@ -73,5 +74,12 @@ public class Startup : BaseStartup
|
||||
{
|
||||
appBranch.UseAccountHandler();
|
||||
});
|
||||
|
||||
app.MapWhen(
|
||||
context => context.Request.Path.ToString().StartsWith(UrlShortRewriter.BasePath),
|
||||
appBranch =>
|
||||
{
|
||||
appBranch.UseUrlShortRewriter();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
68
web/ASC.Web.Core/UrlShortRewriter.cs
Normal file
68
web/ASC.Web.Core/UrlShortRewriter.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Core;
|
||||
public class UrlShortRewriter
|
||||
{
|
||||
public const string BasePath = "/sh/";
|
||||
|
||||
public UrlShortRewriter(RequestDelegate next)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext httpContext, IDbContextFactory<UrlShortenerDbContext> dbContextFactory)
|
||||
{
|
||||
var path = httpContext.Request.Path.ToString();
|
||||
path = path.Substring(BasePath.Length);
|
||||
|
||||
var id = ShortUrl.Decode(path);
|
||||
|
||||
ShortLink link;
|
||||
|
||||
using (var context = dbContextFactory.CreateDbContext())
|
||||
{
|
||||
link = await context.ShortLinks.FindAsync(id);
|
||||
}
|
||||
|
||||
if (link != null)
|
||||
{
|
||||
httpContext.Response.Redirect(link.Link);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Bad Request");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class UrlShortRewriterExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseUrlShortRewriter(this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware<UrlShortRewriter>();
|
||||
}
|
||||
}
|
@ -26,138 +26,144 @@
|
||||
|
||||
namespace ASC.Web.Core.Utility;
|
||||
|
||||
[Scope(Additional = typeof(UrlShortenerExtension))]
|
||||
public interface IUrlShortener
|
||||
{
|
||||
Task<string> GetShortenLinkAsync(string shareLink);
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class UrlShortener
|
||||
public class BaseUrlShortener: IUrlShortener
|
||||
{
|
||||
public bool Enabled { get { return Instance is not NullShortener; } }
|
||||
private readonly ConsumerFactory _consumerFactory;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
private IUrlShortener _instance;
|
||||
public IUrlShortener Instance
|
||||
public BaseUrlShortener(
|
||||
ConsumerFactory consumerFactory,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
if (_consumerFactory.Get<BitlyLoginProvider>().Enabled)
|
||||
{
|
||||
_instance = new BitLyShortener(_consumerFactory);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(_configuration["web:url-shortener:value"]))
|
||||
{
|
||||
_instance = new OnlyoShortener(_configuration, _commonLinkUtility, _machinePseudoKeys, _clientFactory);
|
||||
}
|
||||
else
|
||||
{
|
||||
_instance = new NullShortener();
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
set
|
||||
{
|
||||
_instance = value;
|
||||
}
|
||||
_consumerFactory = consumerFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ConsumerFactory _consumerFactory;
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly MachinePseudoKeys _machinePseudoKeys;
|
||||
private readonly IHttpClientFactory _clientFactory;
|
||||
|
||||
public UrlShortener(
|
||||
IConfiguration configuration,
|
||||
ConsumerFactory consumerFactory,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
MachinePseudoKeys machinePseudoKeys,
|
||||
IHttpClientFactory clientFactory)
|
||||
public Task<string> GetShortenLinkAsync(string shareLink)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_consumerFactory = consumerFactory;
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_machinePseudoKeys = machinePseudoKeys;
|
||||
_clientFactory = clientFactory;
|
||||
IUrlShortener shortener;
|
||||
if (_consumerFactory.Get<BitlyLoginProvider>().Enabled)
|
||||
{
|
||||
shortener = _serviceProvider.GetRequiredService<BitLyShortener>();
|
||||
}
|
||||
else
|
||||
{
|
||||
shortener = _serviceProvider.GetRequiredService<OnlyoShortener>();
|
||||
}
|
||||
|
||||
return shortener.GetShortenLinkAsync(shareLink);
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class BitLyShortener : IUrlShortener
|
||||
{
|
||||
public BitLyShortener(ConsumerFactory consumerFactory)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
}
|
||||
|
||||
|
||||
private ConsumerFactory ConsumerFactory { get; }
|
||||
|
||||
|
||||
public Task<string> GetShortenLinkAsync(string shareLink)
|
||||
{
|
||||
return Task.FromResult(ConsumerFactory.Get<BitlyLoginProvider>().GetShortenLink(shareLink));
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class OnlyoShortener : IUrlShortener
|
||||
{
|
||||
private readonly string _url;
|
||||
private readonly string _internalUrl;
|
||||
private readonly byte[] _sKey;
|
||||
|
||||
private CommonLinkUtility CommonLinkUtility { get; }
|
||||
private IHttpClientFactory ClientFactory { get; }
|
||||
|
||||
public OnlyoShortener(
|
||||
IConfiguration configuration,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
MachinePseudoKeys machinePseudoKeys,
|
||||
IHttpClientFactory clientFactory)
|
||||
private readonly IDbContextFactory<UrlShortenerDbContext> _contextFactory;
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
public OnlyoShortener(IDbContextFactory<UrlShortenerDbContext> contextFactory,
|
||||
CommonLinkUtility commonLinkUtility)
|
||||
{
|
||||
_url = configuration["web:url-shortener:value"];
|
||||
_internalUrl = configuration["web:url-shortener:internal"];
|
||||
_sKey = machinePseudoKeys.GetMachineConstant();
|
||||
|
||||
if (!_url.EndsWith('/'))
|
||||
{
|
||||
_url += '/';
|
||||
}
|
||||
|
||||
CommonLinkUtility = commonLinkUtility;
|
||||
ClientFactory = clientFactory;
|
||||
_contextFactory = contextFactory;
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> GetShortenLinkAsync(string shareLink)
|
||||
{
|
||||
var request = new HttpRequestMessage
|
||||
if (Uri.IsWellFormedUriString(shareLink, UriKind.Absolute))
|
||||
{
|
||||
RequestUri = new Uri(_internalUrl + "?url=" + HttpUtility.UrlEncode(shareLink))
|
||||
};
|
||||
request.Headers.Add("Authorization", CreateAuthToken());
|
||||
request.Headers.Add("Encoding", Encoding.UTF8.ToString());//todo check
|
||||
|
||||
var httpClient = ClientFactory.CreateClient();
|
||||
using var response = await httpClient.SendAsync(request);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||
using var rs = new StreamReader(stream);
|
||||
return CommonLinkUtility.GetFullAbsolutePath(_url + await rs.ReadToEndAsync());
|
||||
}
|
||||
|
||||
private string CreateAuthToken(string pkey = "urlShortener")
|
||||
{
|
||||
using var hasher = new HMACSHA1(_sKey);
|
||||
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
|
||||
var hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
|
||||
return $"ASC {pkey}:{now}:{hash}";
|
||||
var context = _contextFactory.CreateDbContext();
|
||||
var link = await context.ShortLinks.FirstOrDefaultAsync(q=> q.Link == shareLink);
|
||||
if (link != null)
|
||||
{
|
||||
return _commonLinkUtility.GetFullAbsolutePath(UrlShortRewriter.BasePath + link.Short);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var key = ShortUrl.GenerateRandomKey();
|
||||
var id = ShortUrl.Decode(key);
|
||||
var existId = await context.ShortLinks.AnyAsync(q => q.Id == id);
|
||||
if (!existId)
|
||||
{
|
||||
var newShortLink = new ShortLink()
|
||||
{
|
||||
Id = id,
|
||||
Link = shareLink,
|
||||
Short = key
|
||||
};
|
||||
await context.ShortLinks.AddAsync(newShortLink);
|
||||
await context.SaveChangesAsync();
|
||||
return _commonLinkUtility.GetFullAbsolutePath(UrlShortRewriter.BasePath + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return shareLink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NullShortener : IUrlShortener
|
||||
public static class ShortUrl
|
||||
{
|
||||
public Task<string> GetShortenLinkAsync(string shareLink)
|
||||
private const string Alphabet = "5XzpDt6wZRdsTrJkSY_cgPyxN4j-fnb9WKBF8vh3GH72QqmLVCM";
|
||||
private static readonly int _base = Alphabet.Length;
|
||||
|
||||
public static string GenerateRandomKey()
|
||||
{
|
||||
return Task.FromResult<string>(null);
|
||||
var rand = new Random();
|
||||
var length = rand.Next(5, 8);
|
||||
var result = "";
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var x = rand.Next(0, 51);
|
||||
result += Alphabet.ElementAt(x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static long Decode(string str)
|
||||
{
|
||||
long num = 0;
|
||||
for (var i = 0; i < str.Length; i++)
|
||||
{
|
||||
num = num * _base + Alphabet.IndexOf(str.ElementAt(i));
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UrlShortenerExtension
|
||||
{
|
||||
public static void Register(DIHelper dIHelper)
|
||||
{
|
||||
dIHelper.TryAdd<IUrlShortener, BaseUrlShortener>();
|
||||
dIHelper.TryAdd<BitLyShortener>();
|
||||
dIHelper.TryAdd<OnlyoShortener>();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user