Skip to content
Snippets Groups Projects
Commit aa395826 authored by Felix Sidokhine's avatar Felix Sidokhine
Browse files

Added license checking and download skeletons - need logic

parent d7eac716
No related branches found
No related tags found
No related merge requests found
Showing
with 333 additions and 21 deletions
......@@ -8,10 +8,28 @@ servers:
paths:
/api/admin/device:
get:
summary: Your GET endpoint
summary: User device
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
operationId: get-api-admin-device
requestBody:
description: ''
parameters:
- schema:
type: string
in: query
name: username
- schema:
type: string
in: query
name: deviceId
description: Returns the device information.
put:
summary: ''
operationId: put-api-admin-device
......@@ -24,18 +42,48 @@ paths:
responses:
'200':
description: OK
parameters:
- schema:
type: string
in: query
name: username
- schema:
type: string
in: query
name: deviceId
description: Revokes a device.
/api/admin/devices:
get:
summary: Your GET endpoint
summary: User devices
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Device'
operationId: get-api-admin-devices
parameters:
- schema:
type: string
in: query
name: username
/api/admin/directory/entry:
get:
summary: Your GET endpoint
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserProfile'
operationId: get-api-admin-directory-entry
description: ''
put:
summary: ''
operationId: put-api-admin-directory-entry
......@@ -79,4 +127,40 @@ paths:
responses: {}
operationId: get-api-admin-users
components:
schemas: {}
schemas:
Device:
title: Device
type: object
properties:
deviceId:
type: string
displayName:
type: string
certificate:
type: string
description: "The user's Jami device."
UserProfile:
title: UserProfile
type: object
properties:
username:
type: string
firstName:
type: string
lastName:
type: string
phoneNumber:
type: string
phoneNumberExtension:
type: string
mobileNumber:
type: string
faxNumber:
type: string
profilePicture:
type: string
email:
type: string
organization:
type: string
description: "The user's extended information which is not critical to Jami operations, usually provided by LDAP, Active Directory or other backend."
......@@ -28,7 +28,9 @@ paths:
get:
summary: Name lookup
tags: []
responses: {}
responses:
'200':
description: OK
operationId: get-api-nameserver-name-name
components:
schemas: {}
......@@ -7,7 +7,7 @@ servers:
paths:
/api/auth/contacts:
get:
summary: Your GET endpoint
summary: Contacts endpoint
tags: []
responses: {}
operationId: get-api-auth-contacts
......@@ -19,9 +19,15 @@ paths:
in: path
required: true
get:
summary: Your GET endpoint
summary: Device operations
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: './Admin-API.v1.yaml#/components/schemas/Device'
operationId: get-api-auth-device-deviceId
put:
summary: ''
......@@ -35,33 +41,66 @@ paths:
responses:
'200':
description: OK
content:
application/json:
schema:
allOf: []
/api/auth/devices:
get:
summary: Your GET endpoint
summary: Get the list of devices
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: './Admin-API.v1.yaml#/components/schemas/Device'
operationId: get-api-auth-devices
/api/auth/directories:
get:
summary: Your GET endpoint
summary: Get the directories connect to JAMS
tags: []
responses: {}
operationId: get-api-auth-directories
/api/auth/directory/entry:
get:
summary: Your GET endpoint
summary: Get the profile of a user
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: './Admin-API.v1.yaml#/components/schemas/UserProfile'
operationId: get-api-auth-directory-entry
/api/auth/directory/search:
get:
summary: Your GET endpoint
summary: Search the directory
tags: []
responses: {}
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: './Admin-API.v1.yaml#/components/schemas/UserProfile'
'':
content:
application/json:
schema:
type: array
items:
$ref: './Admin-API.v1.yaml#/components/schemas/UserProfile'
operationId: get-api-auth-directory-search
/api/auth/user:
get:
summary: Your GET endpoint
summary: User endpoint
tags: []
responses: {}
operationId: get-api-auth-user
......
......@@ -48,7 +48,7 @@ public class PublicNameServer implements NameServer {
responseData.append((char) con.getInputStream().read());
currentSize++;
}
log.info("Reponse received from public nameserver {} ", responseData.toString());
log.info("Response received from public nameserver {} ", responseData.toString());
return JsonIterator.deserialize(responseData.toString(),NameLookupResponse.class);
}
return null;
......
......@@ -9,12 +9,14 @@ import org.apache.catalina.webresources.DirResourceSet;
import org.apache.catalina.webresources.JarResourceSet;
import org.apache.catalina.webresources.StandardRoot;
import java.awt.*;
import java.io.File;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
//This class boots the tomcat server which provides the subsystem
//for the API calls.
@Slf4j
......@@ -40,6 +42,7 @@ public class TomcatLauncher {
log.info("JAR Resource File = " + jarName);
StandardContext context = (StandardContext) tomcat.addWebapp("", new File(System.getProperty("user.dir")).getAbsolutePath());
//Hack to prevent useless verbose messages.
context.getJarScanner().setJarScanFilter((jarScanType, s) -> false);
WebResourceRoot resources = new StandardRoot(context);
if (jarName.contains(".jar")) {
......@@ -72,6 +75,4 @@ public class TomcatLauncher {
log.error("Web-server has failed to start - this is critical!");
}
}
}
package net.jami.jams.server.servlets.api.update;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/api/update/status")
public class UpdateServlet extends HttpServlet {
//Return the current version number and the available version number.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
//This is the do-update button.
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
package net.jami.jams.server.update;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class SFLTrustStore implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//Doesn't need to be implemented.
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//Needs to be implemented
}
//Implement this.
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
package net.jami.jams.server.update;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
import java.util.List;
import java.util.TimerTask;
import static net.jami.jams.server.update.UpdateDaemon.UPDATE_SERVER_URI;
@Slf4j
public class UpdateCheckTask extends TimerTask {
private final List<String> files;
protected UpdateCheckTask(List<String> files) {
this.files = files;
}
@Override
public void run() {
try {
URL url = new URL(UPDATE_SERVER_URI);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
if (con.getResponseCode() == 200) {
StringBuilder responseData = new StringBuilder();
int respSize = Integer.parseInt(con.getHeaderField("Content-Length"));
int currentSize = 0;
while (currentSize < respSize) {
responseData.append((char) con.getInputStream().read());
currentSize++;
}
log.info("Response received from update server {} ", responseData.toString());
//TODO: Populate the files which "need" to be downloaded.
} else {
log.info("An error has occurred while checking for an update: {} ", con.getResponseCode());
}
}
catch (Exception e){
log.error("Could not check for updates with error: {}",e.getMessage());
}
}
}
package net.jami.jams.server.update;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
public class UpdateDaemon extends Timer {
public static final String UPDATE_SERVER_URI = "https://jami.net";
public static final List<String> updateFiles = new ArrayList<>();
public UpdateDaemon() {
this.schedule(new UpdateCheckTask(updateFiles),0,150_000);
}
}
package net.jami.jams.server.update;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.*;
import java.io.FileOutputStream;
import java.net.URL;
import java.security.KeyStore;
import static net.jami.jams.server.update.UpdateDaemon.UPDATE_SERVER_URI;
@Slf4j
public class UpdateDownloader {
private SSLSocketFactory sslSocketFactory;
public void downloadUpdate(){
try {
if (!loadLicense()) {
log.warn("This server does not have a valid license, no files will be download and no update" +
" will take place...");
return;
}
for(String file : UpdateDaemon.updateFiles) {
URL url = new URL(UPDATE_SERVER_URI);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(sslSocketFactory);
con.setRequestMethod("GET");
if (con.getResponseCode() == 200) {
StringBuilder responseData = new StringBuilder();
int respSize = Integer.parseInt(con.getHeaderField("Content-Length"));
int currentSize = 0;
while (currentSize < respSize) {
responseData.append((char) con.getInputStream().read());
currentSize++;
}
log.info("Succesfully downloaded file...");
} else {
log.info("An error has occurred while trying to download a file: {} ", con.getResponseCode());
}
}
}
catch (Exception e){
log.error("Could not check for updates with error: {}",e.getMessage());
}
}
private boolean loadLicense(){
try {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
char[] password = "changeit".toCharArray();
ks.load(null, password);
//Set the license.
ks.setKeyEntry("license",null,null);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks,"".toCharArray());
//Initialize the SSL context & load the SFL trust store.
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), new SFLTrustStore[]{new SFLTrustStore()},null);
log.info("License loaded successfully!");
sslSocketFactory = sslContext.getSocketFactory();
return true;
}
catch (Exception e){
log.error("An error occurred while trying to load the license: {}",e.getMessage());
return false;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment