Add authentication to uploads
This commit is contained in:
parent
f14da6bafc
commit
ee41e3bcd3
@ -1,4 +1,7 @@
|
||||
{
|
||||
"logPath": "\/var\/log\/caps.log",
|
||||
"serveFiles": true
|
||||
"serveFiles": true,
|
||||
"writers" : [
|
||||
"auth_key_1"
|
||||
]
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ final class CapServer {
|
||||
|
||||
private var saveImmediatelly = true
|
||||
|
||||
private var writers: Set<String>
|
||||
|
||||
private var caps = [Int: Cap]() {
|
||||
didSet {
|
||||
guard saveImmediatelly else {
|
||||
@ -26,12 +28,13 @@ final class CapServer {
|
||||
}
|
||||
|
||||
var nextClassifierVersion: Int {
|
||||
caps.values.map { $0.classifierVersion }.max() ?? 1
|
||||
caps.values.compactMap { $0.classifierVersion }.max() ?? 1
|
||||
}
|
||||
|
||||
init(in folder: URL) throws {
|
||||
init(in folder: URL, writers: [String]) throws {
|
||||
self.imageFolder = folder.appendingPathComponent("images")
|
||||
self.dbFile = folder.appendingPathComponent("caps.json")
|
||||
self.writers = Set(writers)
|
||||
|
||||
var isDirectory: ObjCBool = false
|
||||
guard fm.fileExists(atPath: folder.path, isDirectory: &isDirectory),
|
||||
@ -65,6 +68,17 @@ final class CapServer {
|
||||
func file(of cap: Int, version: Int) -> URL {
|
||||
folder(of: cap).appendingPathComponent(String(format: "%04d-%02d.jpg", cap, version))
|
||||
}
|
||||
|
||||
// MARK: Authentication
|
||||
|
||||
func hasAuthorization(for key: String) -> Bool {
|
||||
// Note: This is not a constant-time compare, so there may be an opportunity
|
||||
// for timing attack here. Sets perform hashed lookups, so this may be less of an issue,
|
||||
// and we're not doing anything critical in this application.
|
||||
// Worst case, an unauthorized person with a lot of free time and energy to hack this system
|
||||
// is able to change contents of the database, which are backed up in any case.
|
||||
writers.contains(key)
|
||||
}
|
||||
|
||||
// MARK: Counts
|
||||
|
||||
|
@ -2,15 +2,20 @@ import Foundation
|
||||
|
||||
struct Config: Codable {
|
||||
|
||||
/// The path to the log file
|
||||
let logPath: String
|
||||
|
||||
/// Serve files in the Public directory using Vapor
|
||||
let serveFiles: Bool
|
||||
|
||||
/// Authentication tokens for remotes allowed to write
|
||||
let writers: [String]
|
||||
|
||||
var logURL: URL {
|
||||
.init(fileURLWithPath: logPath)
|
||||
}
|
||||
|
||||
static var `default`: Config {
|
||||
.init(logPath: "/var/log/caps.log", serveFiles: true)
|
||||
.init(logPath: "/var/log/caps.log", serveFiles: true, writers: [])
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ public func configure(_ app: Application) throws {
|
||||
app.middleware.use(middleware)
|
||||
}
|
||||
|
||||
server = try CapServer(in: URL(fileURLWithPath: publicDirectory))
|
||||
server = try CapServer(in: URL(fileURLWithPath: publicDirectory),
|
||||
writers: config.writers)
|
||||
|
||||
// Register routes to the router
|
||||
try routes(app)
|
||||
|
@ -1,5 +1,12 @@
|
||||
import Vapor
|
||||
|
||||
private func authorize(_ request: Request) throws {
|
||||
let key = try request.query.get(String.self, at: "key")
|
||||
guard server.hasAuthorization(for: key) else {
|
||||
throw Abort(.forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
/// Register your application's routes here.
|
||||
///
|
||||
/// [Learn More →](https://docs.vapor.codes/3.0/getting-started/structure/#routesswift)
|
||||
@ -7,6 +14,7 @@ func routes(_ app: Application) throws {
|
||||
|
||||
// Set the name of a cap
|
||||
app.postCatching("name", ":n") { request in
|
||||
try authorize(request)
|
||||
guard let cap = request.parameters.get("n", as: Int.self) else {
|
||||
log("Invalid parameter for cap")
|
||||
throw Abort(.badRequest)
|
||||
@ -20,6 +28,7 @@ func routes(_ app: Application) throws {
|
||||
|
||||
// Upload an image
|
||||
app.postCatching("images", ":n") { request -> Data in
|
||||
try authorize(request)
|
||||
guard let cap = request.parameters.get("n", as: Int.self) else {
|
||||
log("Invalid parameter for cap")
|
||||
throw Abort(.badRequest)
|
||||
@ -35,6 +44,7 @@ func routes(_ app: Application) throws {
|
||||
|
||||
// Set a different version as the main image
|
||||
app.getCatching("switch", ":n", ":v") { request in
|
||||
try authorize(request)
|
||||
guard let cap = request.parameters.get("n", as: Int.self), cap >= 0 else {
|
||||
log("Invalid parameter for cap")
|
||||
throw Abort(.badRequest)
|
||||
|
Loading…
Reference in New Issue
Block a user