Merge branch 'develop' into feature/rtl-interface-direction
This commit is contained in:
commit
45510eb3bc
@ -109,6 +109,7 @@ public abstract class BaseStartup
|
|||||||
.AddBaseDbContextPool<TelegramDbContext>()
|
.AddBaseDbContextPool<TelegramDbContext>()
|
||||||
.AddBaseDbContextPool<FirebaseDbContext>()
|
.AddBaseDbContextPool<FirebaseDbContext>()
|
||||||
.AddBaseDbContextPool<CustomDbContext>()
|
.AddBaseDbContextPool<CustomDbContext>()
|
||||||
|
.AddBaseDbContextPool<UrlShortenerDbContext>()
|
||||||
.AddBaseDbContextPool<WebstudioDbContext>()
|
.AddBaseDbContextPool<WebstudioDbContext>()
|
||||||
.AddBaseDbContextPool<InstanceRegistrationContext>()
|
.AddBaseDbContextPool<InstanceRegistrationContext>()
|
||||||
.AddBaseDbContextPool<IntegrationEventLogContext>()
|
.AddBaseDbContextPool<IntegrationEventLogContext>()
|
||||||
|
@ -52,6 +52,7 @@ public class BaseWorkerStartup
|
|||||||
services.AddBaseDbContextPool<TelegramDbContext>();
|
services.AddBaseDbContextPool<TelegramDbContext>();
|
||||||
services.AddBaseDbContextPool<FirebaseDbContext>();
|
services.AddBaseDbContextPool<FirebaseDbContext>();
|
||||||
services.AddBaseDbContextPool<CustomDbContext>();
|
services.AddBaseDbContextPool<CustomDbContext>();
|
||||||
|
services.AddBaseDbContextPool<UrlShortenerDbContext>();
|
||||||
services.AddBaseDbContextPool<WebstudioDbContext>();
|
services.AddBaseDbContextPool<WebstudioDbContext>();
|
||||||
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
||||||
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
||||||
|
@ -26,9 +26,11 @@
|
|||||||
|
|
||||||
namespace ASC.Core.Common.EF.Context;
|
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;
|
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 Short { get; set; }
|
||||||
public string Link { get; set; }
|
public string Link { get; set; }
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ public static class ShortLinksExtension
|
|||||||
|
|
||||||
public static void MySqlAddShortLinks(this ModelBuilder modelBuilder)
|
public static void MySqlAddShortLinks(this ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<ShortLinks>(entity =>
|
modelBuilder.Entity<ShortLink>(entity =>
|
||||||
{
|
{
|
||||||
entity.ToTable("short_links")
|
entity.ToTable("short_links")
|
||||||
.HasCharSet("utf8")
|
.HasCharSet("utf8")
|
||||||
@ -61,7 +61,7 @@ public static class ShortLinksExtension
|
|||||||
entity.Property(e => e.Id)
|
entity.Property(e => e.Id)
|
||||||
.HasColumnName("id")
|
.HasColumnName("id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int(10)");
|
.HasColumnType("bigint(19)");
|
||||||
|
|
||||||
entity.Property(e => e.Short)
|
entity.Property(e => e.Short)
|
||||||
.HasColumnName("short")
|
.HasColumnName("short")
|
||||||
@ -80,7 +80,7 @@ public static class ShortLinksExtension
|
|||||||
|
|
||||||
public static void PgSqlAddShortLinks(this ModelBuilder modelBuilder)
|
public static void PgSqlAddShortLinks(this ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<ShortLinks>(entity =>
|
modelBuilder.Entity<ShortLink>(entity =>
|
||||||
{
|
{
|
||||||
entity.ToTable("short_links")
|
entity.ToTable("short_links")
|
||||||
.HasCharSet("utf8")
|
.HasCharSet("utf8")
|
||||||
@ -95,7 +95,7 @@ public static class ShortLinksExtension
|
|||||||
entity.Property(e => e.Id)
|
entity.Property(e => e.Id)
|
||||||
.HasColumnName("id")
|
.HasColumnName("id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int(10)");
|
.HasColumnType("bigint(19)");
|
||||||
|
|
||||||
entity.Property(e => e.Short)
|
entity.Property(e => e.Short)
|
||||||
.HasColumnName("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
|
// (c) Copyright Ascensio System SIA 2010-2022
|
||||||
//
|
//
|
||||||
// This program is a free software product.
|
// This program is a free software product.
|
||||||
// You can redistribute it and/or modify it under the terms
|
// 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
|
// 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
|
// 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
|
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||||
// any third-party rights.
|
// any third-party rights.
|
||||||
//
|
//
|
||||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
// 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.
|
// 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
|
// 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.
|
// 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
|
// 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
|
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||||
// trademark law for use of our trademarks.
|
// trademark law for use of our trademarks.
|
||||||
//
|
//
|
||||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
// 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
|
// 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
|
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
|
||||||
var options = new WebApplicationOptions
|
var options = new WebApplicationOptions
|
||||||
@ -49,4 +49,4 @@ if (!Path.IsPathRooted(conf.Path))
|
|||||||
}
|
}
|
||||||
|
|
||||||
var migrationCreator = new MigrationCreator(app.Services);
|
var migrationCreator = new MigrationCreator(app.Services);
|
||||||
migrationCreator.RunCreateMigrations(conf);
|
migrationCreator.RunCreateMigrations(conf);
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
// (c) Copyright Ascensio System SIA 2010-2022
|
// (c) Copyright Ascensio System SIA 2010-2022
|
||||||
//
|
//
|
||||||
// This program is a free software product.
|
// This program is a free software product.
|
||||||
// You can redistribute it and/or modify it under the terms
|
// 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
|
// 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
|
// 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
|
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||||
// any third-party rights.
|
// any third-party rights.
|
||||||
//
|
//
|
||||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
// 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.
|
// 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
|
// 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.
|
// 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
|
// 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
|
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||||
// trademark law for use of our trademarks.
|
// trademark law for use of our trademarks.
|
||||||
//
|
//
|
||||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
// 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
|
// 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
|
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
|
||||||
var options = new WebApplicationOptions
|
var options = new WebApplicationOptions
|
||||||
@ -48,4 +48,4 @@ foreach (var providerInfo in providersInfo.Providers)
|
|||||||
{
|
{
|
||||||
var migrationCreator = new MigrationRunner(app.Services);
|
var migrationCreator = new MigrationRunner(app.Services);
|
||||||
migrationCreator.RunApplyMigrations(AppContext.BaseDirectory, providerInfo, providersInfo.TeamlabsiteProviders.SingleOrDefault(q => q.Provider == providerInfo.Provider), configurationInfo);
|
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<DbFilesLink> FilesLink { get; set; }
|
||||||
public DbSet<DbFilesProperties> FilesProperties { get; set; }
|
public DbSet<DbFilesProperties> FilesProperties { get; set; }
|
||||||
public DbSet<FilesConverts> FilesConverts { get; set; }
|
public DbSet<FilesConverts> FilesConverts { get; set; }
|
||||||
|
public DbSet<ShortLink> ShortLink { get; set; }
|
||||||
public MigrationContext(DbContextOptions<MigrationContext> options) : base(options) { }
|
public MigrationContext(DbContextOptions<MigrationContext> options) : base(options) { }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
@ -159,6 +160,7 @@ public class MigrationContext : DbContext
|
|||||||
.AddDbWebhooks()
|
.AddDbWebhooks()
|
||||||
.AddWebhooksConfig()
|
.AddWebhooksConfig()
|
||||||
.AddWebhooksLog()
|
.AddWebhooksLog()
|
||||||
|
.AddShortLinks()
|
||||||
.AddDbFunctions();
|
.AddDbFunctions();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,7 +56,8 @@ public class Startup
|
|||||||
services.AddBaseDbContextPool<UserDbContext>();
|
services.AddBaseDbContextPool<UserDbContext>();
|
||||||
services.AddBaseDbContextPool<TelegramDbContext>();
|
services.AddBaseDbContextPool<TelegramDbContext>();
|
||||||
services.AddBaseDbContextPool<FirebaseDbContext>();
|
services.AddBaseDbContextPool<FirebaseDbContext>();
|
||||||
services.AddBaseDbContextPool<CustomDbContext>();
|
services.AddBaseDbContextPool<CustomDbContext>();
|
||||||
|
services.AddBaseDbContextPool<UrlShortenerDbContext>();
|
||||||
services.AddBaseDbContextPool<WebstudioDbContext>();
|
services.AddBaseDbContextPool<WebstudioDbContext>();
|
||||||
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
services.AddBaseDbContextPool<InstanceRegistrationContext>();
|
||||||
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
services.AddBaseDbContextPool<IntegrationEventLogContext>();
|
||||||
|
@ -183,6 +183,10 @@ server {
|
|||||||
proxy_pass http://127.0.0.1:5001;
|
proxy_pass http://127.0.0.1:5001;
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location ~* sh/(.*) {
|
||||||
|
proxy_pass http://127.0.0.1:5000;
|
||||||
|
}
|
||||||
|
|
||||||
location /api/2.0 {
|
location /api/2.0 {
|
||||||
location ~* /(files|privacyroom) {
|
location ~* /(files|privacyroom) {
|
||||||
@ -268,11 +272,6 @@ server {
|
|||||||
rewrite apicache/(.*) /$1 break;
|
rewrite apicache/(.*) /$1 break;
|
||||||
proxy_pass http://127.0.0.1:5100;
|
proxy_pass http://127.0.0.1:5100;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /sh {
|
|
||||||
rewrite sh/(.*) /$1 break;
|
|
||||||
proxy_pass http://127.0.0.1:9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /healthchecks {
|
location /healthchecks {
|
||||||
rewrite /healthchecks/(.*)$ /$1 break;
|
rewrite /healthchecks/(.*)$ /$1 break;
|
||||||
|
@ -4579,6 +4579,37 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
b.HasAnnotation("MySql:CharSet", "utf8");
|
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 =>
|
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("TenantId")
|
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.Metadata;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
@ -1454,6 +1479,24 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
})
|
})
|
||||||
.Annotation("MySql:CharSet", "utf8");
|
.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(
|
migrationBuilder.InsertData(
|
||||||
table: "files_converts",
|
table: "files_converts",
|
||||||
columns: new[] { "input", "output" },
|
columns: new[] { "input", "output" },
|
||||||
@ -2498,6 +2541,12 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
name: "visitdate",
|
name: "visitdate",
|
||||||
table: "webstudio_uservisit",
|
table: "webstudio_uservisit",
|
||||||
column: "visitdate");
|
column: "visitdate");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_short_links_short",
|
||||||
|
table: "short_links",
|
||||||
|
column: "short",
|
||||||
|
unique: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -2667,6 +2716,9 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "tenants_tenants");
|
name: "tenants_tenants");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "short_links");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4576,6 +4576,37 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
b.HasAnnotation("MySql:CharSet", "utf8");
|
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 =>
|
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("TenantId")
|
b.Property<int>("TenantId")
|
||||||
@ -5845,7 +5876,7 @@ namespace ASC.Migrations.MySql.SaaS.Migrations
|
|||||||
.UseCollation("utf8_general_ci")
|
.UseCollation("utf8_general_ci")
|
||||||
.HasAnnotation("MySql:CharSet", "utf8");
|
.HasAnnotation("MySql:CharSet", "utf8");
|
||||||
|
|
||||||
b.Property<string>("FileShareOptions")
|
b.Property<string>("Options")
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("options")
|
.HasColumnName("options")
|
||||||
.UseCollation("utf8_general_ci")
|
.UseCollation("utf8_general_ci")
|
||||||
|
@ -4510,6 +4510,38 @@ namespace ASC.Migrations.PostgreSql.SaaS.Migrations
|
|||||||
b.ToTable("Regions");
|
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 =>
|
modelBuilder.Entity("ASC.Core.Common.EF.Model.TelegramUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("TenantId")
|
b.Property<int>("TenantId")
|
||||||
@ -5718,7 +5750,7 @@ namespace ASC.Migrations.PostgreSql.SaaS.Migrations
|
|||||||
.HasColumnName("subject")
|
.HasColumnName("subject")
|
||||||
.IsFixedLength();
|
.IsFixedLength();
|
||||||
|
|
||||||
b.Property<string>("FileShareOptions")
|
b.Property<string>("Options")
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("options");
|
.HasColumnName("options");
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ const PublicRoomBlock = (props) => {
|
|||||||
setEditLinkPanelIsVisible,
|
setEditLinkPanelIsVisible,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [barIsVisible, setBarVisible] = useState(!isArchiveFolder);
|
|
||||||
|
|
||||||
const onAddNewLink = () => {
|
const onAddNewLink = () => {
|
||||||
setLinkParams({ isEdit: false });
|
setLinkParams({ isEdit: false });
|
||||||
setEditLinkPanelIsVisible(true);
|
setEditLinkPanelIsVisible(true);
|
||||||
@ -29,7 +27,7 @@ const PublicRoomBlock = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{barIsVisible && (
|
{externalLinks.length > 0 && !isArchiveFolder && (
|
||||||
<PublicRoomBar
|
<PublicRoomBar
|
||||||
headerText={t("Files:PublicRoom")}
|
headerText={t("Files:PublicRoom")}
|
||||||
bodyText={t("CreateEditRoomDialog:PublicRoomBarDescription")}
|
bodyText={t("CreateEditRoomDialog:PublicRoomBarDescription")}
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
// 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
|
// 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;
|
namespace ASC.Web.Files.Services.WCFService;
|
||||||
|
|
||||||
[Scope]
|
[Scope]
|
||||||
@ -68,7 +66,7 @@ public class FileStorageService //: IFileStorageService
|
|||||||
private readonly DocumentServiceConnector _documentServiceConnector;
|
private readonly DocumentServiceConnector _documentServiceConnector;
|
||||||
private readonly FileSharing _fileSharing;
|
private readonly FileSharing _fileSharing;
|
||||||
private readonly NotifyClient _notifyClient;
|
private readonly NotifyClient _notifyClient;
|
||||||
private readonly UrlShortener _urlShortener;
|
private readonly IUrlShortener _urlShortener;
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly FileSharingAceHelper _fileSharingAceHelper;
|
private readonly FileSharingAceHelper _fileSharingAceHelper;
|
||||||
private readonly ConsumerFactory _consumerFactory;
|
private readonly ConsumerFactory _consumerFactory;
|
||||||
@ -123,7 +121,7 @@ public class FileStorageService //: IFileStorageService
|
|||||||
DocumentServiceConnector documentServiceConnector,
|
DocumentServiceConnector documentServiceConnector,
|
||||||
FileSharing fileSharing,
|
FileSharing fileSharing,
|
||||||
NotifyClient notifyClient,
|
NotifyClient notifyClient,
|
||||||
UrlShortener urlShortener,
|
IUrlShortener urlShortener,
|
||||||
IServiceProvider serviceProvider,
|
IServiceProvider serviceProvider,
|
||||||
FileSharingAceHelper fileSharingAceHelper,
|
FileSharingAceHelper fileSharingAceHelper,
|
||||||
ConsumerFactory consumerFactory,
|
ConsumerFactory consumerFactory,
|
||||||
@ -2564,7 +2562,7 @@ public class FileStorageService //: IFileStorageService
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _urlShortener.Instance.GetShortenLinkAsync(shareLink);
|
return await _urlShortener.GetShortenLinkAsync(shareLink);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -138,6 +138,7 @@ global using ASC.Web.Core.Notify;
|
|||||||
global using ASC.Web.Core.PublicResources;
|
global using ASC.Web.Core.PublicResources;
|
||||||
global using ASC.Web.Core.Quota;
|
global using ASC.Web.Core.Quota;
|
||||||
global using ASC.Web.Core.Users;
|
global using ASC.Web.Core.Users;
|
||||||
|
global using ASC.Web.Core.Utility;
|
||||||
global using ASC.Web.Core.Utility.Skins;
|
global using ASC.Web.Core.Utility.Skins;
|
||||||
global using ASC.Web.Core.WhiteLabel;
|
global using ASC.Web.Core.WhiteLabel;
|
||||||
global using ASC.Web.Files;
|
global using ASC.Web.Files;
|
||||||
|
@ -1,56 +1,56 @@
|
|||||||
// (c) Copyright Ascensio System SIA 2010-2022
|
// (c) Copyright Ascensio System SIA 2010-2022
|
||||||
//
|
//
|
||||||
// This program is a free software product.
|
// This program is a free software product.
|
||||||
// You can redistribute it and/or modify it under the terms
|
// 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
|
// 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
|
// 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
|
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||||
// any third-party rights.
|
// any third-party rights.
|
||||||
//
|
//
|
||||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
// 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.
|
// 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
|
// 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.
|
// 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
|
// 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
|
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||||
// trademark law for use of our trademarks.
|
// trademark law for use of our trademarks.
|
||||||
//
|
//
|
||||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
// 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
|
// 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
|
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
|
||||||
namespace ASC.Web.Api.Controllers;
|
namespace ASC.Web.Api.Controllers;
|
||||||
|
|
||||||
[Scope]
|
[Scope]
|
||||||
[DefaultRoute]
|
[DefaultRoute]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class PortalController : ControllerBase
|
public class PortalController : ControllerBase
|
||||||
{
|
{
|
||||||
protected Tenant Tenant { get { return _apiContext.Tenant; } }
|
protected Tenant Tenant { get { return _apiContext.Tenant; } }
|
||||||
|
|
||||||
private readonly ApiContext _apiContext;
|
private readonly ApiContext _apiContext;
|
||||||
protected readonly UserManager _userManager;
|
protected readonly UserManager _userManager;
|
||||||
protected readonly TenantManager _tenantManager;
|
protected readonly TenantManager _tenantManager;
|
||||||
protected readonly ITariffService _tariffService;
|
protected readonly ITariffService _tariffService;
|
||||||
private readonly CommonLinkUtility _commonLinkUtility;
|
private readonly CommonLinkUtility _commonLinkUtility;
|
||||||
private readonly UrlShortener _urlShortener;
|
private readonly IUrlShortener _urlShortener;
|
||||||
private readonly AuthContext _authContext;
|
private readonly AuthContext _authContext;
|
||||||
private readonly WebItemSecurity _webItemSecurity;
|
private readonly WebItemSecurity _webItemSecurity;
|
||||||
protected readonly SecurityContext _securityContext;
|
protected readonly SecurityContext _securityContext;
|
||||||
private readonly SettingsManager _settingsManager;
|
private readonly SettingsManager _settingsManager;
|
||||||
private readonly IMobileAppInstallRegistrator _mobileAppInstallRegistrator;
|
private readonly IMobileAppInstallRegistrator _mobileAppInstallRegistrator;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
private readonly CoreBaseSettings _coreBaseSettings;
|
private readonly CoreBaseSettings _coreBaseSettings;
|
||||||
private readonly LicenseReader _licenseReader;
|
private readonly LicenseReader _licenseReader;
|
||||||
private readonly SetupInfo _setupInfo;
|
private readonly SetupInfo _setupInfo;
|
||||||
private readonly DocumentServiceLicense _documentServiceLicense;
|
private readonly DocumentServiceLicense _documentServiceLicense;
|
||||||
private readonly TenantExtra _tenantExtra;
|
private readonly TenantExtra _tenantExtra;
|
||||||
private readonly ILogger<PortalController> _log;
|
private readonly ILogger<PortalController> _log;
|
||||||
private readonly IHttpClientFactory _clientFactory;
|
private readonly IHttpClientFactory _clientFactory;
|
||||||
private readonly ApiSystemHelper _apiSystemHelper;
|
private readonly ApiSystemHelper _apiSystemHelper;
|
||||||
private readonly CoreSettings _coreSettings;
|
private readonly CoreSettings _coreSettings;
|
||||||
@ -67,25 +67,25 @@ public class PortalController : ControllerBase
|
|||||||
private readonly QuotaHelper _quotaHelper;
|
private readonly QuotaHelper _quotaHelper;
|
||||||
private readonly IEventBus _eventBus;
|
private readonly IEventBus _eventBus;
|
||||||
|
|
||||||
public PortalController(
|
public PortalController(
|
||||||
ILogger<PortalController> logger,
|
ILogger<PortalController> logger,
|
||||||
ApiContext apiContext,
|
ApiContext apiContext,
|
||||||
UserManager userManager,
|
UserManager userManager,
|
||||||
TenantManager tenantManager,
|
TenantManager tenantManager,
|
||||||
ITariffService tariffService,
|
ITariffService tariffService,
|
||||||
CommonLinkUtility commonLinkUtility,
|
CommonLinkUtility commonLinkUtility,
|
||||||
UrlShortener urlShortener,
|
IUrlShortener urlShortener,
|
||||||
AuthContext authContext,
|
AuthContext authContext,
|
||||||
WebItemSecurity webItemSecurity,
|
WebItemSecurity webItemSecurity,
|
||||||
SecurityContext securityContext,
|
SecurityContext securityContext,
|
||||||
SettingsManager settingsManager,
|
SettingsManager settingsManager,
|
||||||
IMobileAppInstallRegistrator mobileAppInstallRegistrator,
|
IMobileAppInstallRegistrator mobileAppInstallRegistrator,
|
||||||
TenantExtra tenantExtra,
|
TenantExtra tenantExtra,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
CoreBaseSettings coreBaseSettings,
|
CoreBaseSettings coreBaseSettings,
|
||||||
LicenseReader licenseReader,
|
LicenseReader licenseReader,
|
||||||
SetupInfo setupInfo,
|
SetupInfo setupInfo,
|
||||||
DocumentServiceLicense documentServiceLicense,
|
DocumentServiceLicense documentServiceLicense,
|
||||||
IHttpClientFactory clientFactory,
|
IHttpClientFactory clientFactory,
|
||||||
ApiSystemHelper apiSystemHelper,
|
ApiSystemHelper apiSystemHelper,
|
||||||
CoreSettings coreSettings,
|
CoreSettings coreSettings,
|
||||||
@ -101,25 +101,25 @@ public class PortalController : ControllerBase
|
|||||||
IHttpContextAccessor httpContextAccessor,
|
IHttpContextAccessor httpContextAccessor,
|
||||||
QuotaHelper quotaHelper,
|
QuotaHelper quotaHelper,
|
||||||
IEventBus eventBus)
|
IEventBus eventBus)
|
||||||
{
|
{
|
||||||
_log = logger;
|
_log = logger;
|
||||||
_apiContext = apiContext;
|
_apiContext = apiContext;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_tenantManager = tenantManager;
|
_tenantManager = tenantManager;
|
||||||
_tariffService = tariffService;
|
_tariffService = tariffService;
|
||||||
_commonLinkUtility = commonLinkUtility;
|
_commonLinkUtility = commonLinkUtility;
|
||||||
_urlShortener = urlShortener;
|
_urlShortener = urlShortener;
|
||||||
_authContext = authContext;
|
_authContext = authContext;
|
||||||
_webItemSecurity = webItemSecurity;
|
_webItemSecurity = webItemSecurity;
|
||||||
_securityContext = securityContext;
|
_securityContext = securityContext;
|
||||||
_settingsManager = settingsManager;
|
_settingsManager = settingsManager;
|
||||||
_mobileAppInstallRegistrator = mobileAppInstallRegistrator;
|
_mobileAppInstallRegistrator = mobileAppInstallRegistrator;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
_coreBaseSettings = coreBaseSettings;
|
_coreBaseSettings = coreBaseSettings;
|
||||||
_licenseReader = licenseReader;
|
_licenseReader = licenseReader;
|
||||||
_setupInfo = setupInfo;
|
_setupInfo = setupInfo;
|
||||||
_documentServiceLicense = documentServiceLicense;
|
_documentServiceLicense = documentServiceLicense;
|
||||||
_tenantExtra = tenantExtra;
|
_tenantExtra = tenantExtra;
|
||||||
_clientFactory = clientFactory;
|
_clientFactory = clientFactory;
|
||||||
_apiSystemHelper = apiSystemHelper;
|
_apiSystemHelper = apiSystemHelper;
|
||||||
_coreSettings = coreSettings;
|
_coreSettings = coreSettings;
|
||||||
@ -135,61 +135,61 @@ public class PortalController : ControllerBase
|
|||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
_quotaHelper = quotaHelper;
|
_quotaHelper = quotaHelper;
|
||||||
_eventBus = eventBus;
|
_eventBus = eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
public TenantDto Get()
|
public TenantDto Get()
|
||||||
{
|
{
|
||||||
return _mapper.Map<TenantDto>(Tenant);
|
return _mapper.Map<TenantDto>(Tenant);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("users/{userID}")]
|
[HttpGet("users/{userID}")]
|
||||||
public async Task<UserInfo> GetUserAsync(Guid userID)
|
public async Task<UserInfo> GetUserAsync(Guid userID)
|
||||||
{
|
{
|
||||||
return await _userManager.GetUsersAsync(userID);
|
return await _userManager.GetUsersAsync(userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("users/invite/{employeeType}")]
|
[HttpGet("users/invite/{employeeType}")]
|
||||||
public async Task<object> GeInviteLinkAsync(EmployeeType employeeType)
|
public async Task<object> GeInviteLinkAsync(EmployeeType employeeType)
|
||||||
{
|
{
|
||||||
if (!await _permissionContext.CheckPermissionsAsync(new UserSecurityProvider(Guid.Empty, employeeType), ASC.Core.Users.Constants.Action_AddRemoveUser))
|
if (!await _permissionContext.CheckPermissionsAsync(new UserSecurityProvider(Guid.Empty, employeeType), ASC.Core.Users.Constants.Action_AddRemoveUser))
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await _commonLinkUtility.GetConfirmationEmailUrlAsync(string.Empty, ConfirmType.LinkInvite, (int)employeeType, _authContext.CurrentAccount.ID)
|
return await _commonLinkUtility.GetConfirmationEmailUrlAsync(string.Empty, ConfirmType.LinkInvite, (int)employeeType, _authContext.CurrentAccount.ID)
|
||||||
+ $"&emplType={employeeType:d}";
|
+ $"&emplType={employeeType:d}";
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("getshortenlink")]
|
[HttpPut("getshortenlink")]
|
||||||
public async Task<object> GetShortenLinkAsync(ShortenLinkRequestsDto inDto)
|
public async Task<object> GetShortenLinkAsync(ShortenLinkRequestsDto inDto)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _urlShortener.Instance.GetShortenLinkAsync(inDto.Link);
|
return await _urlShortener.GetShortenLinkAsync(inDto.Link);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.ErrorGetShortenLink(ex);
|
_log.ErrorGetShortenLink(ex);
|
||||||
return inDto.Link;
|
return inDto.Link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowNotPayment, AllowAnonymous]
|
[AllowNotPayment, AllowAnonymous]
|
||||||
[HttpGet("tenantextra")]
|
[HttpGet("tenantextra")]
|
||||||
public async Task<TenantExtraDto> GetTenantExtra(bool refresh)
|
public async Task<TenantExtraDto> GetTenantExtra(bool refresh)
|
||||||
{
|
{
|
||||||
var result = new TenantExtraDto
|
var result = new TenantExtraDto
|
||||||
{
|
{
|
||||||
CustomMode = _coreBaseSettings.CustomMode,
|
CustomMode = _coreBaseSettings.CustomMode,
|
||||||
Opensource = _tenantExtra.Opensource,
|
Opensource = _tenantExtra.Opensource,
|
||||||
Enterprise = _tenantExtra.Enterprise,
|
Enterprise = _tenantExtra.Enterprise,
|
||||||
EnableTariffPage = //TenantExtra.EnableTarrifSettings - think about hide-settings for opensource
|
EnableTariffPage = //TenantExtra.EnableTarrifSettings - think about hide-settings for opensource
|
||||||
(!_coreBaseSettings.Standalone || !string.IsNullOrEmpty(_licenseReader.LicensePath))
|
(!_coreBaseSettings.Standalone || !string.IsNullOrEmpty(_licenseReader.LicensePath))
|
||||||
&& string.IsNullOrEmpty(_setupInfo.AmiMetaUrl)
|
&& string.IsNullOrEmpty(_setupInfo.AmiMetaUrl)
|
||||||
&& !_coreBaseSettings.CustomMode
|
&& !_coreBaseSettings.CustomMode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -201,120 +201,120 @@ public class PortalController : ControllerBase
|
|||||||
result.LicenseAccept = _settingsManager.LoadForDefaultTenant<TariffSettings>().LicenseAcceptSetting;
|
result.LicenseAccept = _settingsManager.LoadForDefaultTenant<TariffSettings>().LicenseAcceptSetting;
|
||||||
result.DocServerUserQuota = await _documentServiceLicense.GetLicenseQuotaAsync();
|
result.DocServerUserQuota = await _documentServiceLicense.GetLicenseQuotaAsync();
|
||||||
result.DocServerLicense = await _documentServiceLicense.GetLicenseAsync();
|
result.DocServerLicense = await _documentServiceLicense.GetLicenseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet("usedspace")]
|
||||||
[HttpGet("usedspace")]
|
|
||||||
public async Task<double> GetUsedSpaceAsync()
|
public async Task<double> GetUsedSpaceAsync()
|
||||||
{
|
{
|
||||||
return Math.Round(
|
return Math.Round(
|
||||||
(await _tenantManager.FindTenantQuotaRowsAsync(Tenant.Id))
|
(await _tenantManager.FindTenantQuotaRowsAsync(Tenant.Id))
|
||||||
.Where(q => !string.IsNullOrEmpty(q.Tag) && new Guid(q.Tag) != Guid.Empty)
|
.Where(q => !string.IsNullOrEmpty(q.Tag) && new Guid(q.Tag) != Guid.Empty)
|
||||||
.Sum(q => q.Counter) / 1024f / 1024f / 1024f, 2);
|
.Sum(q => q.Counter) / 1024f / 1024f / 1024f, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("userscount")]
|
[HttpGet("userscount")]
|
||||||
public async Task<long> GetUsersCountAsync()
|
public async Task<long> GetUsersCountAsync()
|
||||||
{
|
{
|
||||||
return _coreBaseSettings.Personal ? 1 : (await _userManager.GetUserNamesAsync(EmployeeStatus.Active)).Length;
|
return _coreBaseSettings.Personal ? 1 : (await _userManager.GetUserNamesAsync(EmployeeStatus.Active)).Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
[HttpGet("tariff")]
|
[HttpGet("tariff")]
|
||||||
public async Task<Tariff> GetTariffAsync(bool refresh)
|
public async Task<Tariff> GetTariffAsync(bool refresh)
|
||||||
{
|
{
|
||||||
return await _tariffService.GetTariffAsync(Tenant.Id, refresh: refresh);
|
return await _tariffService.GetTariffAsync(Tenant.Id, refresh: refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
[HttpGet("quota")]
|
[HttpGet("quota")]
|
||||||
public async Task<TenantQuota> GetQuotaAsync()
|
public async Task<TenantQuota> GetQuotaAsync()
|
||||||
{
|
{
|
||||||
return await _tenantManager.GetTenantQuotaAsync(Tenant.Id);
|
return await _tenantManager.GetTenantQuotaAsync(Tenant.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("quota/right")]
|
[HttpGet("quota/right")]
|
||||||
public async Task<TenantQuota> GetRightQuotaAsync()
|
public async Task<TenantQuota> GetRightQuotaAsync()
|
||||||
{
|
{
|
||||||
var usedSpace = await GetUsedSpaceAsync();
|
var usedSpace = await GetUsedSpaceAsync();
|
||||||
var needUsersCount = await GetUsersCountAsync();
|
var needUsersCount = await GetUsersCountAsync();
|
||||||
|
|
||||||
return (await _tenantManager.GetTenantQuotasAsync()).OrderBy(r => r.Price)
|
return (await _tenantManager.GetTenantQuotasAsync()).OrderBy(r => r.Price)
|
||||||
.FirstOrDefault(quota =>
|
.FirstOrDefault(quota =>
|
||||||
quota.CountUser > needUsersCount
|
quota.CountUser > needUsersCount
|
||||||
&& quota.MaxTotalSize > usedSpace);
|
&& quota.MaxTotalSize > usedSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("path")]
|
[HttpGet("path")]
|
||||||
public object GetFullAbsolutePath(string virtualPath)
|
public object GetFullAbsolutePath(string virtualPath)
|
||||||
{
|
{
|
||||||
return _commonLinkUtility.GetFullAbsolutePath(virtualPath);
|
return _commonLinkUtility.GetFullAbsolutePath(virtualPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("thumb")]
|
[HttpGet("thumb")]
|
||||||
public FileResult GetThumb(string url)
|
public FileResult GetThumb(string url)
|
||||||
{
|
{
|
||||||
if (!_securityContext.IsAuthenticated || _configuration["bookmarking:thumbnail-url"] == null)
|
if (!_securityContext.IsAuthenticated || _configuration["bookmarking:thumbnail-url"] == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
url = url.Replace("&", "&");
|
url = url.Replace("&", "&");
|
||||||
url = WebUtility.UrlEncode(url);
|
url = WebUtility.UrlEncode(url);
|
||||||
|
|
||||||
var request = new HttpRequestMessage
|
var request = new HttpRequestMessage
|
||||||
{
|
{
|
||||||
RequestUri = new Uri(string.Format(_configuration["bookmarking:thumbnail-url"], url))
|
RequestUri = new Uri(string.Format(_configuration["bookmarking:thumbnail-url"], url))
|
||||||
};
|
};
|
||||||
|
|
||||||
var httpClient = _clientFactory.CreateClient();
|
var httpClient = _clientFactory.CreateClient();
|
||||||
using var response = httpClient.Send(request);
|
using var response = httpClient.Send(request);
|
||||||
using var stream = response.Content.ReadAsStream();
|
using var stream = response.Content.ReadAsStream();
|
||||||
var bytes = new byte[stream.Length];
|
var bytes = new byte[stream.Length];
|
||||||
stream.Read(bytes, 0, (int)stream.Length);
|
stream.Read(bytes, 0, (int)stream.Length);
|
||||||
|
|
||||||
string type;
|
string type;
|
||||||
if (response.Headers.TryGetValues("Content-Type", out var values))
|
if (response.Headers.TryGetValues("Content-Type", out var values))
|
||||||
{
|
{
|
||||||
type = values.First();
|
type = values.First();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = "image/png";
|
type = "image/png";
|
||||||
}
|
}
|
||||||
return File(bytes, type);
|
return File(bytes, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("present/mark")]
|
[HttpPost("present/mark")]
|
||||||
public async Task MarkPresentAsReadedAsync()
|
public async Task MarkPresentAsReadedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var settings = await _settingsManager.LoadForCurrentUserAsync<OpensourceGiftSettings>();
|
var settings = await _settingsManager.LoadForCurrentUserAsync<OpensourceGiftSettings>();
|
||||||
settings.Readed = true;
|
settings.Readed = true;
|
||||||
await _settingsManager.SaveForCurrentUserAsync(settings);
|
await _settingsManager.SaveForCurrentUserAsync(settings);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.ErrorMarkPresentAsReaded(ex);
|
_log.ErrorMarkPresentAsReaded(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("mobile/registration")]
|
[HttpPost("mobile/registration")]
|
||||||
public async Task RegisterMobileAppInstallAsync(MobileAppRequestsDto inDto)
|
public async Task RegisterMobileAppInstallAsync(MobileAppRequestsDto inDto)
|
||||||
{
|
{
|
||||||
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
||||||
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, inDto.Type);
|
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, inDto.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("mobile/registration")]
|
[HttpPost("mobile/registration")]
|
||||||
public async Task RegisterMobileAppInstallAsync(MobileAppType type)
|
public async Task RegisterMobileAppInstallAsync(MobileAppType type)
|
||||||
{
|
{
|
||||||
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
var currentUser = await _userManager.GetUsersAsync(_securityContext.CurrentAccount.ID);
|
||||||
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, type);
|
await _mobileAppInstallRegistrator.RegisterInstallAsync(currentUser.Email, type);
|
||||||
}
|
}
|
||||||
@ -576,5 +576,5 @@ public class PortalController : ControllerBase
|
|||||||
default:
|
default:
|
||||||
throw new SecurityException("Access Denied.");
|
throw new SecurityException("Access Denied.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,12 +24,12 @@
|
|||||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
// 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
|
// 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
|
public class SettingsController : BaseSettingsController
|
||||||
{
|
{
|
||||||
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
|
||||||
private Tenant Tenant { get { return ApiContext.Tenant; } }
|
private Tenant Tenant { get { return ApiContext.Tenant; } }
|
||||||
|
|
||||||
private readonly MessageService _messageService;
|
private readonly MessageService _messageService;
|
||||||
private readonly ConsumerFactory _consumerFactory;
|
private readonly ConsumerFactory _consumerFactory;
|
||||||
@ -51,18 +51,17 @@ public class SettingsController : BaseSettingsController
|
|||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
private readonly SetupInfo _setupInfo;
|
private readonly SetupInfo _setupInfo;
|
||||||
private readonly StatisticManager _statisticManager;
|
private readonly StatisticManager _statisticManager;
|
||||||
private readonly UrlShortener _urlShortener;
|
|
||||||
private readonly PasswordHasher _passwordHasher;
|
private readonly PasswordHasher _passwordHasher;
|
||||||
private readonly ILogger _log;
|
private readonly ILogger _log;
|
||||||
private readonly TelegramHelper _telegramHelper;
|
private readonly TelegramHelper _telegramHelper;
|
||||||
private readonly DnsSettings _dnsSettings;
|
private readonly DnsSettings _dnsSettings;
|
||||||
private readonly AdditionalWhiteLabelSettingsHelperInit _additionalWhiteLabelSettingsHelper;
|
private readonly AdditionalWhiteLabelSettingsHelperInit _additionalWhiteLabelSettingsHelper;
|
||||||
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
|
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
|
||||||
private readonly QuotaUsageManager _quotaUsageManager;
|
private readonly QuotaUsageManager _quotaUsageManager;
|
||||||
private readonly TenantDomainValidator _tenantDomainValidator;
|
private readonly TenantDomainValidator _tenantDomainValidator;
|
||||||
private readonly QuotaSyncOperation _quotaSyncOperation;
|
private readonly QuotaSyncOperation _quotaSyncOperation;
|
||||||
private readonly ExternalShare _externalShare;
|
private readonly ExternalShare _externalShare;
|
||||||
|
|
||||||
public SettingsController(
|
public SettingsController(
|
||||||
ILoggerProvider option,
|
ILoggerProvider option,
|
||||||
MessageService messageService,
|
MessageService messageService,
|
||||||
@ -89,16 +88,15 @@ public class SettingsController : BaseSettingsController
|
|||||||
ProviderManager providerManager,
|
ProviderManager providerManager,
|
||||||
FirstTimeTenantSettings firstTimeTenantSettings,
|
FirstTimeTenantSettings firstTimeTenantSettings,
|
||||||
TelegramHelper telegramHelper,
|
TelegramHelper telegramHelper,
|
||||||
UrlShortener urlShortener,
|
PasswordHasher passwordHasher,
|
||||||
PasswordHasher passwordHasher,
|
IHttpContextAccessor httpContextAccessor,
|
||||||
IHttpContextAccessor httpContextAccessor,
|
DnsSettings dnsSettings,
|
||||||
DnsSettings dnsSettings,
|
AdditionalWhiteLabelSettingsHelperInit additionalWhiteLabelSettingsHelper,
|
||||||
AdditionalWhiteLabelSettingsHelperInit additionalWhiteLabelSettingsHelper,
|
|
||||||
CustomColorThemesSettingsHelper customColorThemesSettingsHelper,
|
CustomColorThemesSettingsHelper customColorThemesSettingsHelper,
|
||||||
QuotaSyncOperation quotaSyncOperation,
|
QuotaSyncOperation quotaSyncOperation,
|
||||||
QuotaUsageManager quotaUsageManager,
|
QuotaUsageManager quotaUsageManager,
|
||||||
TenantDomainValidator tenantDomainValidator,
|
TenantDomainValidator tenantDomainValidator,
|
||||||
ExternalShare externalShare
|
ExternalShare externalShare
|
||||||
) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
|
) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
|
||||||
{
|
{
|
||||||
_log = option.CreateLogger("ASC.Api");
|
_log = option.CreateLogger("ASC.Api");
|
||||||
@ -106,7 +104,7 @@ public class SettingsController : BaseSettingsController
|
|||||||
_timeZoneConverter = timeZoneConverter;
|
_timeZoneConverter = timeZoneConverter;
|
||||||
_customNamingPeople = customNamingPeople;
|
_customNamingPeople = customNamingPeople;
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
_firstTimeTenantSettings = firstTimeTenantSettings;
|
_firstTimeTenantSettings = firstTimeTenantSettings;
|
||||||
_messageService = messageService;
|
_messageService = messageService;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_tenantManager = tenantManager;
|
_tenantManager = tenantManager;
|
||||||
@ -123,45 +121,44 @@ public class SettingsController : BaseSettingsController
|
|||||||
_setupInfo = setupInfo;
|
_setupInfo = setupInfo;
|
||||||
_statisticManager = statisticManager;
|
_statisticManager = statisticManager;
|
||||||
_passwordHasher = passwordHasher;
|
_passwordHasher = passwordHasher;
|
||||||
_urlShortener = urlShortener;
|
_telegramHelper = telegramHelper;
|
||||||
_telegramHelper = telegramHelper;
|
_dnsSettings = dnsSettings;
|
||||||
_dnsSettings = dnsSettings;
|
_additionalWhiteLabelSettingsHelper = additionalWhiteLabelSettingsHelper;
|
||||||
_additionalWhiteLabelSettingsHelper = additionalWhiteLabelSettingsHelper;
|
|
||||||
_quotaSyncOperation = quotaSyncOperation;
|
_quotaSyncOperation = quotaSyncOperation;
|
||||||
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
|
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
|
||||||
_quotaUsageManager = quotaUsageManager;
|
_quotaUsageManager = quotaUsageManager;
|
||||||
_tenantDomainValidator = tenantDomainValidator;
|
_tenantDomainValidator = tenantDomainValidator;
|
||||||
_externalShare = externalShare;
|
_externalShare = externalShare;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
[AllowNotPayment, AllowSuspended, AllowAnonymous]
|
[AllowNotPayment, AllowSuspended, AllowAnonymous]
|
||||||
public async Task<SettingsDto> GetSettingsAsync(bool? withpassword)
|
public async Task<SettingsDto> GetSettingsAsync(bool? withpassword)
|
||||||
{
|
{
|
||||||
var studioAdminMessageSettings = await _settingsManager.LoadAsync<StudioAdminMessageSettings>();
|
var studioAdminMessageSettings = await _settingsManager.LoadAsync<StudioAdminMessageSettings>();
|
||||||
var tenantCookieSettings = _settingsManager.Load<TenantCookieSettings>();
|
var tenantCookieSettings = _settingsManager.Load<TenantCookieSettings>();
|
||||||
|
|
||||||
var settings = new SettingsDto
|
var settings = new SettingsDto
|
||||||
{
|
{
|
||||||
Culture = Tenant.GetCulture().ToString(),
|
Culture = Tenant.GetCulture().ToString(),
|
||||||
GreetingSettings = Tenant.Name == "" ? Resource.PortalName : Tenant.Name,
|
GreetingSettings = Tenant.Name == "" ? Resource.PortalName : Tenant.Name,
|
||||||
Personal = _coreBaseSettings.Personal,
|
Personal = _coreBaseSettings.Personal,
|
||||||
DocSpace = !_coreBaseSettings.DisableDocSpace,
|
DocSpace = !_coreBaseSettings.DisableDocSpace,
|
||||||
Standalone = _coreBaseSettings.Standalone,
|
Standalone = _coreBaseSettings.Standalone,
|
||||||
BaseDomain = _coreBaseSettings.Basedomain,
|
BaseDomain = _coreBaseSettings.Basedomain,
|
||||||
Version = _configuration["version:number"] ?? "",
|
Version = _configuration["version:number"] ?? "",
|
||||||
TenantStatus = (await _tenantManager.GetCurrentTenantAsync()).Status,
|
TenantStatus = (await _tenantManager.GetCurrentTenantAsync()).Status,
|
||||||
TenantAlias = Tenant.Alias,
|
TenantAlias = Tenant.Alias,
|
||||||
EnableAdmMess = studioAdminMessageSettings.Enable || await _tenantExtra.IsNotPaidAsync(),
|
EnableAdmMess = studioAdminMessageSettings.Enable || await _tenantExtra.IsNotPaidAsync(),
|
||||||
LegalTerms = _setupInfo.LegalTerms,
|
LegalTerms = _setupInfo.LegalTerms,
|
||||||
CookieSettingsEnabled = tenantCookieSettings.Enabled
|
CookieSettingsEnabled = tenantCookieSettings.Enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!_authContext.IsAuthenticated && await _externalShare.GetLinkIdAsync() != default)
|
if (!_authContext.IsAuthenticated && await _externalShare.GetLinkIdAsync() != default)
|
||||||
{
|
{
|
||||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_authContext.IsAuthenticated)
|
if (_authContext.IsAuthenticated)
|
||||||
{
|
{
|
||||||
settings.TrustedDomains = Tenant.TrustedDomains;
|
settings.TrustedDomains = Tenant.TrustedDomains;
|
||||||
@ -172,11 +169,11 @@ public class SettingsController : BaseSettingsController
|
|||||||
settings.UtcHoursOffset = settings.UtcOffset.TotalHours;
|
settings.UtcHoursOffset = settings.UtcOffset.TotalHours;
|
||||||
settings.OwnerId = Tenant.OwnerId;
|
settings.OwnerId = Tenant.OwnerId;
|
||||||
settings.NameSchemaId = _customNamingPeople.Current.Id;
|
settings.NameSchemaId = _customNamingPeople.Current.Id;
|
||||||
settings.DomainValidator = _tenantDomainValidator;
|
settings.DomainValidator = _tenantDomainValidator;
|
||||||
settings.ZendeskKey = _setupInfo.ZendeskKey;
|
settings.ZendeskKey = _setupInfo.ZendeskKey;
|
||||||
settings.BookTrainingEmail = _setupInfo.BookTrainingEmail;
|
settings.BookTrainingEmail = _setupInfo.BookTrainingEmail;
|
||||||
settings.DocumentationEmail = _setupInfo.DocumentationEmail;
|
settings.DocumentationEmail = _setupInfo.DocumentationEmail;
|
||||||
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
settings.SocketUrl = _configuration["web:hub:url"] ?? "";
|
||||||
|
|
||||||
settings.Firebase = new FirebaseDto
|
settings.Firebase = new FirebaseDto
|
||||||
{
|
{
|
||||||
@ -186,32 +183,32 @@ public class SettingsController : BaseSettingsController
|
|||||||
StorageBucket = _configuration["firebase:storageBucket"] ?? "",
|
StorageBucket = _configuration["firebase:storageBucket"] ?? "",
|
||||||
MessagingSenderId = _configuration["firebase:messagingSenderId"] ?? "",
|
MessagingSenderId = _configuration["firebase:messagingSenderId"] ?? "",
|
||||||
AppId = _configuration["firebase:appId"] ?? "",
|
AppId = _configuration["firebase:appId"] ?? "",
|
||||||
MeasurementId = _configuration["firebase:measurementId"] ?? "",
|
MeasurementId = _configuration["firebase:measurementId"] ?? "",
|
||||||
DatabaseURL = _configuration["firebase:databaseURL"] ?? ""
|
DatabaseURL = _configuration["firebase:databaseURL"] ?? ""
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.HelpLink = await _commonLinkUtility.GetHelpLinkAsync(_settingsManager, _additionalWhiteLabelSettingsHelper, true);
|
settings.HelpLink = await _commonLinkUtility.GetHelpLinkAsync(_settingsManager, _additionalWhiteLabelSettingsHelper, true);
|
||||||
settings.ApiDocsLink = _configuration["web:api-docs"];
|
settings.ApiDocsLink = _configuration["web:api-docs"];
|
||||||
|
|
||||||
bool debugInfo;
|
bool debugInfo;
|
||||||
if (bool.TryParse(_configuration["debug-info:enabled"], out debugInfo))
|
if (bool.TryParse(_configuration["debug-info:enabled"], out debugInfo))
|
||||||
{
|
{
|
||||||
settings.DebugInfo = debugInfo;
|
settings.DebugInfo = debugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.Plugins = new PluginsDto();
|
settings.Plugins = new PluginsDto();
|
||||||
|
|
||||||
bool pluginsEnabled;
|
bool pluginsEnabled;
|
||||||
if (bool.TryParse(_configuration["plugins:enabled"], out pluginsEnabled))
|
if (bool.TryParse(_configuration["plugins:enabled"], out pluginsEnabled))
|
||||||
{
|
{
|
||||||
settings.Plugins.Enabled = pluginsEnabled;
|
settings.Plugins.Enabled = pluginsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.Plugins.Allow = _configuration.GetSection("plugins:allow").Get<List<string>>() ?? new List<string>();
|
settings.Plugins.Allow = _configuration.GetSection("plugins:allow").Get<List<string>>() ?? new List<string>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(await _settingsManager.LoadAsync<WizardSettings>()).Completed)
|
if (!(await _settingsManager.LoadAsync<WizardSettings>()).Completed)
|
||||||
{
|
{
|
||||||
settings.WizardToken = _commonLinkUtility.GetToken(Tenant.Id, "", ConfirmType.Wizard, userId: Tenant.OwnerId);
|
settings.WizardToken = _commonLinkUtility.GetToken(Tenant.Id, "", ConfirmType.Wizard, userId: Tenant.OwnerId);
|
||||||
}
|
}
|
||||||
@ -241,13 +238,13 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("maildomainsettings")]
|
[HttpPost("maildomainsettings")]
|
||||||
public async Task<object> SaveMailDomainSettingsAsync(MailDomainSettingsRequestsDto inDto)
|
public async Task<object> SaveMailDomainSettingsAsync(MailDomainSettingsRequestsDto inDto)
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||||
|
|
||||||
if (inDto.Type == TenantTrustedDomainsType.Custom)
|
if (inDto.Type == TenantTrustedDomainsType.Custom)
|
||||||
{
|
{
|
||||||
Tenant.TrustedDomainsRaw = "";
|
Tenant.TrustedDomainsRaw = "";
|
||||||
Tenant.TrustedDomains.Clear();
|
Tenant.TrustedDomains.Clear();
|
||||||
foreach (var d in inDto.Domains.Select(domain => (domain ?? "").Trim().ToLower()))
|
foreach (var d in inDto.Domains.Select(domain => (domain ?? "").Trim().ToLower()))
|
||||||
{
|
{
|
||||||
@ -267,11 +264,11 @@ public class SettingsController : BaseSettingsController
|
|||||||
|
|
||||||
Tenant.TrustedDomainsType = inDto.Type;
|
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;
|
return Resource.SuccessfullySaveSettingsMessage;
|
||||||
}
|
}
|
||||||
@ -283,16 +280,16 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("userquotasettings")]
|
[HttpPost("userquotasettings")]
|
||||||
public async Task<object> SaveUserQuotaSettingsAsync(UserQuotaSettingsRequestsDto inDto)
|
public async Task<object> SaveUserQuotaSettingsAsync(UserQuotaSettingsRequestsDto inDto)
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
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;
|
return Resource.SuccessfullySaveSettingsMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
[HttpGet("cultures")]
|
[HttpGet("cultures")]
|
||||||
public IEnumerable<object> GetSupportedCultures()
|
public IEnumerable<object> GetSupportedCultures()
|
||||||
@ -301,11 +298,11 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard,Administrators")]
|
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard,Administrators")]
|
||||||
[HttpGet("timezones")]
|
[HttpGet("timezones")]
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
public async Task<List<TimezonesRequestsDto>> GetTimeZonesAsyncAsync()
|
public async Task<List<TimezonesRequestsDto>> GetTimeZonesAsyncAsync()
|
||||||
{
|
{
|
||||||
await ApiContext.AuthByClaimAsync();
|
await ApiContext.AuthByClaimAsync();
|
||||||
var timeZones = TimeZoneInfo.GetSystemTimeZones().ToList();
|
var timeZones = TimeZoneInfo.GetSystemTimeZones().ToList();
|
||||||
|
|
||||||
if (timeZones.All(tz => tz.Id != "UTC"))
|
if (timeZones.All(tz => tz.Id != "UTC"))
|
||||||
@ -328,193 +325,193 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
||||||
[HttpGet("machine")]
|
[HttpGet("machine")]
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
public object GetMachineName()
|
public object GetMachineName()
|
||||||
{
|
{
|
||||||
return Dns.GetHostName().ToLowerInvariant();
|
return Dns.GetHostName().ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("dns")]
|
[HttpPut("dns")]
|
||||||
public async Task<object> SaveDnsSettingsAsync(DnsSettingsRequestsDto model)
|
public async Task<object> SaveDnsSettingsAsync(DnsSettingsRequestsDto model)
|
||||||
{
|
{
|
||||||
return await _dnsSettings.SaveDnsSettingsAsync(model.DnsName, model.Enable);
|
return await _dnsSettings.SaveDnsSettingsAsync(model.DnsName, model.Enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("recalculatequota")]
|
[HttpGet("recalculatequota")]
|
||||||
public async Task RecalculateQuotaAsync()
|
public async Task RecalculateQuotaAsync()
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||||
_quotaSyncOperation.RecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
_quotaSyncOperation.RecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("checkrecalculatequota")]
|
[HttpGet("checkrecalculatequota")]
|
||||||
public async Task<bool> CheckRecalculateQuotaAsync()
|
public async Task<bool> CheckRecalculateQuotaAsync()
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||||
return _quotaSyncOperation.CheckRecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
return _quotaSyncOperation.CheckRecalculateQuota(await _tenantManager.GetCurrentTenantAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("logo")]
|
[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]
|
[AllowNotPayment]
|
||||||
[HttpPut("wizard/complete")]
|
[HttpPut("wizard/complete")]
|
||||||
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
[Authorize(AuthenticationSchemes = "confirm", Roles = "Wizard")]
|
||||||
public async Task<WizardSettings> CompleteWizardAsync(WizardRequestsDto inDto)
|
public async Task<WizardSettings> CompleteWizardAsync(WizardRequestsDto inDto)
|
||||||
{
|
{
|
||||||
await ApiContext.AuthByClaimAsync();
|
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>
|
///<visible>false</visible>
|
||||||
[HttpPut("welcome/close")]
|
[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.");
|
throw new NotSupportedException("Not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
collaboratorPopupSettings.FirstVisit = false;
|
collaboratorPopupSettings.FirstVisit = false;
|
||||||
await _settingsManager.SaveForCurrentUserAsync(collaboratorPopupSettings);
|
await _settingsManager.SaveForCurrentUserAsync(collaboratorPopupSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowAnonymous, AllowNotPayment, AllowSuspended]
|
[AllowAnonymous, AllowNotPayment, AllowSuspended]
|
||||||
[HttpGet("colortheme")]
|
[HttpGet("colortheme")]
|
||||||
public async Task<CustomColorThemesSettingsDto> GetColorThemeAsync()
|
public async Task<CustomColorThemesSettingsDto> GetColorThemeAsync()
|
||||||
{
|
{
|
||||||
return new CustomColorThemesSettingsDto(await _settingsManager.LoadAsync<CustomColorThemesSettings>(), _customColorThemesSettingsHelper.Limit);
|
return new CustomColorThemesSettingsDto(await _settingsManager.LoadAsync<CustomColorThemesSettings>(), _customColorThemesSettingsHelper.Limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("colortheme")]
|
[HttpPut("colortheme")]
|
||||||
public async Task<CustomColorThemesSettingsDto> SaveColorThemeAsync(CustomColorThemesSettingsRequestsDto inDto)
|
public async Task<CustomColorThemesSettingsDto> SaveColorThemeAsync(CustomColorThemesSettingsRequestsDto inDto)
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||||
|
|
||||||
if (inDto.Theme != null)
|
if (inDto.Theme != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _semaphore.WaitAsync();
|
await _semaphore.WaitAsync();
|
||||||
var theme = inDto.Theme;
|
var theme = inDto.Theme;
|
||||||
|
|
||||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == theme.Id))
|
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == theme.Id))
|
||||||
{
|
{
|
||||||
theme.Id = 0;
|
theme.Id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingItem = settings.Themes.SingleOrDefault(r => r.Id == theme.Id);
|
var settingItem = settings.Themes.SingleOrDefault(r => r.Id == theme.Id);
|
||||||
if (settingItem != null)
|
if (settingItem != null)
|
||||||
{
|
{
|
||||||
if (theme.Main != null)
|
if (theme.Main != null)
|
||||||
{
|
{
|
||||||
settingItem.Main = new CustomColorThemesSettingsColorItem
|
settingItem.Main = new CustomColorThemesSettingsColorItem
|
||||||
{
|
{
|
||||||
Accent = theme.Main.Accent,
|
Accent = theme.Main.Accent,
|
||||||
Buttons = theme.Main.Buttons
|
Buttons = theme.Main.Buttons
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (theme.Text != null)
|
if (theme.Text != null)
|
||||||
{
|
{
|
||||||
settingItem.Text = new CustomColorThemesSettingsColorItem
|
settingItem.Text = new CustomColorThemesSettingsColorItem
|
||||||
{
|
{
|
||||||
Accent = theme.Text.Accent,
|
Accent = theme.Text.Accent,
|
||||||
Buttons = theme.Text.Buttons
|
Buttons = theme.Text.Buttons
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_customColorThemesSettingsHelper.Limit == 0 || settings.Themes.Count < _customColorThemesSettingsHelper.Limit)
|
if (_customColorThemesSettingsHelper.Limit == 0 || settings.Themes.Count < _customColorThemesSettingsHelper.Limit)
|
||||||
{
|
{
|
||||||
if (theme.Id == 0)
|
if (theme.Id == 0)
|
||||||
{
|
{
|
||||||
theme.Id = settings.Themes.Max(r => r.Id) + 1;
|
theme.Id = settings.Themes.Max(r => r.Id) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
theme.Name = "";
|
theme.Name = "";
|
||||||
settings.Themes = settings.Themes.Append(theme).ToList();
|
settings.Themes = settings.Themes.Append(theme).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await _settingsManager.SaveAsync(settings);
|
await _settingsManager.SaveAsync(settings);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_semaphore.Release();
|
_semaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inDto.Selected.HasValue && settings.Themes.Any(r => r.Id == inDto.Selected.Value))
|
if (inDto.Selected.HasValue && settings.Themes.Any(r => r.Id == inDto.Selected.Value))
|
||||||
{
|
{
|
||||||
settings.Selected = inDto.Selected.Value;
|
settings.Selected = inDto.Selected.Value;
|
||||||
await _settingsManager.SaveAsync(settings);
|
await _settingsManager.SaveAsync(settings);
|
||||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("colortheme")]
|
[HttpDelete("colortheme")]
|
||||||
public async Task<CustomColorThemesSettingsDto> DeleteColorThemeAsync(int id)
|
public async Task<CustomColorThemesSettingsDto> DeleteColorThemeAsync(int id)
|
||||||
{
|
{
|
||||||
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
|
||||||
|
|
||||||
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
var settings = await _settingsManager.LoadAsync<CustomColorThemesSettings>();
|
||||||
|
|
||||||
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == id))
|
if (CustomColorThemesSettingsItem.Default.Any(r => r.Id == id))
|
||||||
{
|
{
|
||||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.Themes = settings.Themes.Where(r => r.Id != id).ToList();
|
settings.Themes = settings.Themes.Where(r => r.Id != id).ToList();
|
||||||
|
|
||||||
if (settings.Selected == id)
|
if (settings.Selected == id)
|
||||||
{
|
{
|
||||||
settings.Selected = settings.Themes.Min(r => r.Id);
|
settings.Selected = settings.Themes.Min(r => r.Id);
|
||||||
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
await _messageService.SendAsync(MessageAction.ColorThemeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _settingsManager.SaveAsync(settings);
|
await _settingsManager.SaveAsync(settings);
|
||||||
|
|
||||||
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("closeadminhelper")]
|
[HttpPut("closeadminhelper")]
|
||||||
public async Task CloseAdminHelperAsync()
|
public async Task CloseAdminHelperAsync()
|
||||||
{
|
{
|
||||||
if (!await _userManager.IsDocSpaceAdminAsync(_authContext.CurrentAccount.ID) || _coreBaseSettings.CustomMode || !_coreBaseSettings.Standalone)
|
if (!await _userManager.IsDocSpaceAdminAsync(_authContext.CurrentAccount.ID) || _coreBaseSettings.CustomMode || !_coreBaseSettings.Standalone)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("Not available.");
|
throw new NotSupportedException("Not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminHelperSettings = await _settingsManager.LoadForCurrentUserAsync<AdminHelperSettings>();
|
var adminHelperSettings = await _settingsManager.LoadForCurrentUserAsync<AdminHelperSettings>();
|
||||||
adminHelperSettings.Viewed = true;
|
adminHelperSettings.Viewed = true;
|
||||||
await _settingsManager.SaveForCurrentUserAsync(adminHelperSettings);
|
await _settingsManager.SaveForCurrentUserAsync(adminHelperSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
///<visible>false</visible>
|
///<visible>false</visible>
|
||||||
[HttpPut("timeandlanguage")]
|
[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);
|
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;
|
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) || changelng)
|
||||||
{
|
{
|
||||||
if (!Tenant.TimeZone.Equals(oldTimeZone))
|
if (!Tenant.TimeZone.Equals(oldTimeZone))
|
||||||
{
|
{
|
||||||
await _messageService.SendAsync(MessageAction.TimeZoneSettingsUpdated);
|
await _messageService.SendAsync(MessageAction.TimeZoneSettingsUpdated);
|
||||||
}
|
}
|
||||||
if (changelng)
|
if (changelng)
|
||||||
{
|
{
|
||||||
await _messageService.SendAsync(MessageAction.LanguageSettingsUpdated);
|
await _messageService.SendAsync(MessageAction.LanguageSettingsUpdated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Resource.SuccessfullySaveSettingsMessage;
|
return Resource.SuccessfullySaveSettingsMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
///<visible>false</visible>
|
///<visible>false</visible>
|
||||||
[HttpPut("defaultpage")]
|
[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;
|
return Resource.SuccessfullySaveSettingsMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("emailactivation")]
|
[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;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("statistics/spaceusage/{id}")]
|
[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)
|
var webitem = _webItemManagerSecurity.GetItems(WebZoneType.All, ItemAvailableState.All)
|
||||||
.FirstOrDefault(item =>
|
.FirstOrDefault(item =>
|
||||||
@ -587,7 +584,7 @@ public class SettingsController : BaseSettingsController
|
|||||||
|
|
||||||
if (webitem == null)
|
if (webitem == null)
|
||||||
{
|
{
|
||||||
return new List<UsageSpaceStatItemDto>();
|
return new List<UsageSpaceStatItemDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var statData = await webitem.Context.SpaceUsageStatManager.GetStatDataAsync();
|
var statData = await webitem.Context.SpaceUsageStatManager.GetStatDataAsync();
|
||||||
@ -603,9 +600,9 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("statistics/visit")]
|
[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 from = _tenantUtil.DateTimeFromUtc(fromDate);
|
||||||
var to = _tenantUtil.DateTimeFromUtc(toDate);
|
var to = _tenantUtil.DateTimeFromUtc(toDate);
|
||||||
@ -628,8 +625,8 @@ public class SettingsController : BaseSettingsController
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var hits = await _statisticManager.GetHitsByPeriodAsync(Tenant.Id, from, to);
|
var hits = await _statisticManager.GetHitsByPeriodAsync(Tenant.Id, from, to);
|
||||||
var hosts = await _statisticManager.GetHostsByPeriodAsync(Tenant.Id, from, to);
|
var hosts = await _statisticManager.GetHostsByPeriodAsync(Tenant.Id, from, to);
|
||||||
|
|
||||||
if (hits.Count == 0 || hosts.Count == 0)
|
if (hits.Count == 0 || hosts.Count == 0)
|
||||||
{
|
{
|
||||||
@ -689,11 +686,11 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("authservice")]
|
[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))
|
if (!SetupInfo.IsVisibleSettings(nameof(ManagementType.ThirdPartyAuthorization))
|
||||||
|| !saveAvailable)
|
|| !saveAvailable)
|
||||||
{
|
{
|
||||||
@ -701,25 +698,10 @@ public class SettingsController : BaseSettingsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var changed = false;
|
var changed = false;
|
||||||
var consumer = _consumerFactory.GetByKey<Consumer>(inDto.Name);
|
var consumer = _consumerFactory.GetByKey<Consumer>(inDto.Name);
|
||||||
|
|
||||||
var validateKeyProvider = consumer as IValidateKeysProvider;
|
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)))
|
if (inDto.Props.All(r => string.IsNullOrEmpty(r.Value)))
|
||||||
{
|
{
|
||||||
consumer.Clear();
|
consumer.Clear();
|
||||||
@ -739,7 +721,7 @@ public class SettingsController : BaseSettingsController
|
|||||||
? consumer.ManagedKeys.All(key => string.IsNullOrEmpty(consumer[key]))
|
? consumer.ManagedKeys.All(key => string.IsNullOrEmpty(consumer[key]))
|
||||||
: consumer.All(r => string.IsNullOrEmpty(r.Value));
|
: consumer.All(r => string.IsNullOrEmpty(r.Value));
|
||||||
|
|
||||||
if (validateKeyProvider != null && !await validateKeyProvider.ValidateKeysAsync() && !allPropsIsEmpty)
|
if (validateKeyProvider != null && !await validateKeyProvider.ValidateKeysAsync() && !allPropsIsEmpty)
|
||||||
{
|
{
|
||||||
consumer.Clear();
|
consumer.Clear();
|
||||||
throw new ArgumentException(Resource.ErrorBadKeys);
|
throw new ArgumentException(Resource.ErrorBadKeys);
|
||||||
@ -747,24 +729,24 @@ public class SettingsController : BaseSettingsController
|
|||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
await _messageService.SendAsync(MessageAction.AuthorizationKeysSetting);
|
await _messageService.SendAsync(MessageAction.AuthorizationKeysSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
[AllowNotPayment]
|
[AllowNotPayment]
|
||||||
[HttpGet("payment")]
|
[HttpGet("payment")]
|
||||||
public async Task<object> PaymentSettingsAsync()
|
public async Task<object> PaymentSettingsAsync()
|
||||||
{
|
{
|
||||||
var settings = await _settingsManager.LoadForDefaultTenantAsync<AdditionalWhiteLabelSettings>();
|
var settings = await _settingsManager.LoadForDefaultTenantAsync<AdditionalWhiteLabelSettings>();
|
||||||
var currentQuota = await _tenantManager.GetCurrentTenantQuotaAsync();
|
var currentQuota = await _tenantManager.GetCurrentTenantQuotaAsync();
|
||||||
var currentTariff = await _tenantExtra.GetCurrentTariffAsync();
|
var currentTariff = await _tenantExtra.GetCurrentTariffAsync();
|
||||||
|
|
||||||
if (!int.TryParse(_configuration["core:payment:max-quantity"], out var maxQuotaQuantity))
|
if (!int.TryParse(_configuration["core:payment:max-quantity"], out var maxQuotaQuantity))
|
||||||
{
|
{
|
||||||
maxQuotaQuantity = 999;
|
maxQuotaQuantity = 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
new
|
new
|
||||||
@ -777,7 +759,7 @@ public class SettingsController : BaseSettingsController
|
|||||||
{
|
{
|
||||||
currentQuota.Trial,
|
currentQuota.Trial,
|
||||||
currentTariff.DueDate.Date
|
currentTariff.DueDate.Date
|
||||||
},
|
},
|
||||||
max = maxQuotaQuantity
|
max = maxQuotaQuantity
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -809,17 +791,17 @@ public class SettingsController : BaseSettingsController
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>0 - not connected, 1 - connected, 2 - awaiting confirmation</returns>
|
/// <returns>0 - not connected, 1 - connected, 2 - awaiting confirmation</returns>
|
||||||
[HttpGet("telegramisconnected")]
|
[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>
|
/// <summary>
|
||||||
/// Unlinks TelegramBot from your account
|
/// Unlinks TelegramBot from your account
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpDelete("telegramdisconnect")]
|
[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>();
|
services.AddHostedService<LdapNotifyService>();
|
||||||
DIHelper.TryAdd<LdapNotifyService>();
|
DIHelper.TryAdd<LdapNotifyService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
services.AddBaseDbContextPool<FilesDbContext>();
|
services.AddBaseDbContextPool<FilesDbContext>();
|
||||||
services.AddBaseDbContextPool<BackupsContext>();
|
services.AddBaseDbContextPool<BackupsContext>();
|
||||||
|
|
||||||
@ -73,5 +74,12 @@ public class Startup : BaseStartup
|
|||||||
{
|
{
|
||||||
appBranch.UseAccountHandler();
|
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;
|
namespace ASC.Web.Core.Utility;
|
||||||
|
|
||||||
|
[Scope(Additional = typeof(UrlShortenerExtension))]
|
||||||
public interface IUrlShortener
|
public interface IUrlShortener
|
||||||
{
|
{
|
||||||
Task<string> GetShortenLinkAsync(string shareLink);
|
Task<string> GetShortenLinkAsync(string shareLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Scope]
|
[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 BaseUrlShortener(
|
||||||
public IUrlShortener Instance
|
ConsumerFactory consumerFactory,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
get
|
_consumerFactory = consumerFactory;
|
||||||
{
|
_serviceProvider = serviceProvider;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IConfiguration _configuration;
|
public Task<string> GetShortenLinkAsync(string shareLink)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
IUrlShortener shortener;
|
||||||
_consumerFactory = consumerFactory;
|
if (_consumerFactory.Get<BitlyLoginProvider>().Enabled)
|
||||||
_commonLinkUtility = commonLinkUtility;
|
{
|
||||||
_machinePseudoKeys = machinePseudoKeys;
|
shortener = _serviceProvider.GetRequiredService<BitLyShortener>();
|
||||||
_clientFactory = clientFactory;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shortener = _serviceProvider.GetRequiredService<OnlyoShortener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortener.GetShortenLinkAsync(shareLink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Scope]
|
||||||
public class BitLyShortener : IUrlShortener
|
public class BitLyShortener : IUrlShortener
|
||||||
{
|
{
|
||||||
public BitLyShortener(ConsumerFactory consumerFactory)
|
public BitLyShortener(ConsumerFactory consumerFactory)
|
||||||
{
|
{
|
||||||
ConsumerFactory = consumerFactory;
|
ConsumerFactory = consumerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConsumerFactory ConsumerFactory { get; }
|
private ConsumerFactory ConsumerFactory { get; }
|
||||||
|
|
||||||
public Task<string> GetShortenLinkAsync(string shareLink)
|
public Task<string> GetShortenLinkAsync(string shareLink)
|
||||||
{
|
{
|
||||||
return Task.FromResult(ConsumerFactory.Get<BitlyLoginProvider>().GetShortenLink(shareLink));
|
return Task.FromResult(ConsumerFactory.Get<BitlyLoginProvider>().GetShortenLink(shareLink));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Scope]
|
||||||
public class OnlyoShortener : IUrlShortener
|
public class OnlyoShortener : IUrlShortener
|
||||||
{
|
{
|
||||||
private readonly string _url;
|
private readonly IDbContextFactory<UrlShortenerDbContext> _contextFactory;
|
||||||
private readonly string _internalUrl;
|
private readonly CommonLinkUtility _commonLinkUtility;
|
||||||
private readonly byte[] _sKey;
|
public OnlyoShortener(IDbContextFactory<UrlShortenerDbContext> contextFactory,
|
||||||
|
CommonLinkUtility commonLinkUtility)
|
||||||
private CommonLinkUtility CommonLinkUtility { get; }
|
|
||||||
private IHttpClientFactory ClientFactory { get; }
|
|
||||||
|
|
||||||
public OnlyoShortener(
|
|
||||||
IConfiguration configuration,
|
|
||||||
CommonLinkUtility commonLinkUtility,
|
|
||||||
MachinePseudoKeys machinePseudoKeys,
|
|
||||||
IHttpClientFactory clientFactory)
|
|
||||||
{
|
{
|
||||||
_url = configuration["web:url-shortener:value"];
|
_contextFactory = contextFactory;
|
||||||
_internalUrl = configuration["web:url-shortener:internal"];
|
_commonLinkUtility = commonLinkUtility;
|
||||||
_sKey = machinePseudoKeys.GetMachineConstant();
|
|
||||||
|
|
||||||
if (!_url.EndsWith('/'))
|
|
||||||
{
|
|
||||||
_url += '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonLinkUtility = commonLinkUtility;
|
|
||||||
ClientFactory = clientFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetShortenLinkAsync(string shareLink)
|
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))
|
var context = _contextFactory.CreateDbContext();
|
||||||
};
|
var link = await context.ShortLinks.FirstOrDefaultAsync(q=> q.Link == shareLink);
|
||||||
request.Headers.Add("Authorization", CreateAuthToken());
|
if (link != null)
|
||||||
request.Headers.Add("Encoding", Encoding.UTF8.ToString());//todo check
|
{
|
||||||
|
return _commonLinkUtility.GetFullAbsolutePath(UrlShortRewriter.BasePath + link.Short);
|
||||||
var httpClient = ClientFactory.CreateClient();
|
}
|
||||||
using var response = await httpClient.SendAsync(request);
|
else
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
{
|
||||||
using var rs = new StreamReader(stream);
|
while (true)
|
||||||
return CommonLinkUtility.GetFullAbsolutePath(_url + await rs.ReadToEndAsync());
|
{
|
||||||
}
|
var key = ShortUrl.GenerateRandomKey();
|
||||||
|
var id = ShortUrl.Decode(key);
|
||||||
private string CreateAuthToken(string pkey = "urlShortener")
|
var existId = await context.ShortLinks.AnyAsync(q => q.Id == id);
|
||||||
{
|
if (!existId)
|
||||||
using var hasher = new HMACSHA1(_sKey);
|
{
|
||||||
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
|
var newShortLink = new ShortLink()
|
||||||
var hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
|
{
|
||||||
return $"ASC {pkey}:{now}:{hash}";
|
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