Compare commits
2 commits
63f705e693
...
2542e3f05e
Author | SHA1 | Date | |
---|---|---|---|
2542e3f05e | |||
16af80ac0c |
9 changed files with 133 additions and 136 deletions
64
README.md
64
README.md
|
@ -1,62 +1,10 @@
|
||||||
# rwws
|
# rwws - RealWeather Web Server
|
||||||
|
|
||||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
This contacts APIs instead of the servers because we scrape some and we don't want to draw attention
|
||||||
|
|
||||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
### Usage
|
||||||
|
See `RUNNING.md`[^1]
|
||||||
|
|
||||||
## Running the application in dev mode
|
---
|
||||||
|
|
||||||
You can run your application in dev mode that enables live coding using:
|
[^1]: This is the default Quarkus readme that I wish was available online
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw compile quarkus:dev
|
|
||||||
```
|
|
||||||
|
|
||||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
|
||||||
|
|
||||||
## Packaging and running the application
|
|
||||||
|
|
||||||
The application can be packaged using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package
|
|
||||||
```
|
|
||||||
|
|
||||||
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
|
|
||||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
|
|
||||||
|
|
||||||
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
|
|
||||||
|
|
||||||
If you want to build an _über-jar_, execute the following command:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dquarkus.package.jar.type=uber-jar
|
|
||||||
```
|
|
||||||
|
|
||||||
The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
|
|
||||||
|
|
||||||
## Creating a native executable
|
|
||||||
|
|
||||||
You can create a native executable using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dnative
|
|
||||||
```
|
|
||||||
|
|
||||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
|
||||||
|
|
||||||
```shell script
|
|
||||||
./mvnw package -Dnative -Dquarkus.native.container-build=true
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then execute your native executable with: `./target/rwws-1.0.0-SNAPSHOT-runner`
|
|
||||||
|
|
||||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/maven-tooling>.
|
|
||||||
|
|
||||||
## Provided Code
|
|
||||||
|
|
||||||
### REST
|
|
||||||
|
|
||||||
Easily start your REST Web Services
|
|
||||||
|
|
||||||
[Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources)
|
|
62
RUNNING.md
Normal file
62
RUNNING.md
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# rwws
|
||||||
|
|
||||||
|
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||||
|
|
||||||
|
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||||
|
|
||||||
|
## Running the application in dev mode
|
||||||
|
|
||||||
|
You can run your application in dev mode that enables live coding using:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
./mvnw compile quarkus:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||||
|
|
||||||
|
## Packaging and running the application
|
||||||
|
|
||||||
|
The application can be packaged using:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
./mvnw package
|
||||||
|
```
|
||||||
|
|
||||||
|
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
|
||||||
|
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
|
||||||
|
|
||||||
|
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
|
||||||
|
|
||||||
|
If you want to build an _über-jar_, execute the following command:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
./mvnw package -Dquarkus.package.jar.type=uber-jar
|
||||||
|
```
|
||||||
|
|
||||||
|
The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
|
||||||
|
|
||||||
|
## Creating a native executable
|
||||||
|
|
||||||
|
You can create a native executable using:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
./mvnw package -Dnative
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
./mvnw package -Dnative -Dquarkus.native.container-build=true
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then execute your native executable with: `./target/rwws-1.0.0-SNAPSHOT-runner`
|
||||||
|
|
||||||
|
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/maven-tooling>.
|
||||||
|
|
||||||
|
## Provided Code
|
||||||
|
|
||||||
|
### REST
|
||||||
|
|
||||||
|
Easily start your REST Web Services
|
||||||
|
|
||||||
|
[Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources)
|
|
@ -16,11 +16,11 @@ public class Startup {
|
||||||
AccountService accountService;
|
AccountService accountService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void loadUsers(@Observes StartupEvent event) {
|
public void loadUsers(@Observes StartupEvent ignoredEvent) {
|
||||||
Account.deleteAll();
|
Account.deleteAll();
|
||||||
byte[] adminKey = new byte[18];
|
byte[] adminKey = new byte[18];
|
||||||
|
|
||||||
UserManager.add(adminKey, "admin");
|
accountService.add(adminKey, "admin");
|
||||||
System.out.println("Admin user created: " + Base64.getEncoder().encodeToString(adminKey));
|
System.out.println("Admin user created: " + Base64.getEncoder().encodeToString(adminKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
package eu.m724;
|
|
||||||
|
|
||||||
import eu.m724.orm.AccessKey;
|
|
||||||
import eu.m724.orm.AccessLimits;
|
|
||||||
import eu.m724.orm.Account;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
// TODO figure out all this maybe move to account service
|
|
||||||
public class UserManager {
|
|
||||||
private static final SecureRandom random = new SecureRandom();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates an account with the specified key
|
|
||||||
* @param masterKey the desired master key
|
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
public static void add(byte[] masterKey, String role) {
|
|
||||||
Account account = new Account();
|
|
||||||
account.masterKey = masterKey;
|
|
||||||
account.role = role;
|
|
||||||
account.persist();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates an account with random key
|
|
||||||
* the account's role is "user"
|
|
||||||
* @return base64 encoded key
|
|
||||||
*/
|
|
||||||
public static String create() {
|
|
||||||
return create("user");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates an account with random key
|
|
||||||
* @param role new account's role
|
|
||||||
* @return base64 encoded key
|
|
||||||
*/
|
|
||||||
public static String create(String role) {
|
|
||||||
byte[] key = new byte[18]; // 144 bits of entropy
|
|
||||||
random.nextBytes(key);
|
|
||||||
|
|
||||||
add(key, role);
|
|
||||||
return Base64.getEncoder().encodeToString(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* generates an access key for this account
|
|
||||||
* @return base64 encoded access key
|
|
||||||
*/
|
|
||||||
public static String createMaster(Account account, AccessLimits accessLimits) {
|
|
||||||
byte[] key = new byte[18];
|
|
||||||
random.nextBytes(key);
|
|
||||||
|
|
||||||
AccessKey accessKey = new AccessKey();
|
|
||||||
accessKey.key = key;
|
|
||||||
accessKey.account = account;
|
|
||||||
accessKey.accessLimits = accessLimits;
|
|
||||||
accessKey.persist();
|
|
||||||
|
|
||||||
return Base64.getEncoder().encodeToString(key);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.m724;
|
package eu.m724;
|
||||||
|
|
||||||
|
import eu.m724.auth.master.AccountService;
|
||||||
import eu.m724.orm.Account;
|
import eu.m724.orm.Account;
|
||||||
import io.quarkus.security.identity.SecurityIdentity;
|
import io.quarkus.security.identity.SecurityIdentity;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
@ -17,11 +18,14 @@ public class UsersResource {
|
||||||
@Inject
|
@Inject
|
||||||
SecurityIdentity securityIdentity;
|
SecurityIdentity securityIdentity;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AccountService accountService;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/create")
|
@Path("/create")
|
||||||
@RolesAllowed("admin")
|
@RolesAllowed("admin")
|
||||||
public JsonObject createAccount() {
|
public JsonObject createAccount() {
|
||||||
String masterKey = UserManager.create();
|
String masterKey = accountService.create("user");
|
||||||
|
|
||||||
return Json.createObjectBuilder()
|
return Json.createObjectBuilder()
|
||||||
.add("masterKey", masterKey)
|
.add("masterKey", masterKey)
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
package eu.m724.auth.master;
|
package eu.m724.auth.master;
|
||||||
|
|
||||||
|
import eu.m724.orm.AccessKey;
|
||||||
|
import eu.m724.orm.AccessLimits;
|
||||||
import eu.m724.orm.Account;
|
import eu.m724.orm.Account;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class AccountService {
|
public class AccountService {
|
||||||
|
private final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find a master user by key
|
* find a master user by key
|
||||||
* @param key base64 encoded key
|
* @param key base64 encoded key
|
||||||
|
@ -18,9 +23,53 @@ public class AccountService {
|
||||||
if (key == null) return null;
|
if (key == null) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Account.find("masterKey", Base64.getDecoder().decode(key)).firstResult();
|
return Account.find("masterKey", (Object) Base64.getDecoder().decode(key)).firstResult();
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO maybe move some of these methods somewhere else and reconsider making them static
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an account with the specified key
|
||||||
|
* @param masterKey the desired master key
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void add(byte[] masterKey, String role) {
|
||||||
|
Account account = new Account();
|
||||||
|
account.masterKey = masterKey;
|
||||||
|
account.role = role;
|
||||||
|
account.persist();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an account with random key
|
||||||
|
* @param role new account's role
|
||||||
|
* @return base64 encoded key
|
||||||
|
*/
|
||||||
|
public String create(String role) {
|
||||||
|
byte[] key = new byte[18]; // 144 bits of entropy
|
||||||
|
random.nextBytes(key);
|
||||||
|
|
||||||
|
add(key, role);
|
||||||
|
return Base64.getEncoder().encodeToString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generates an access key for an account
|
||||||
|
* @return base64 encoded access key
|
||||||
|
*/
|
||||||
|
public String createAccessKey(Account account, AccessLimits accessLimits) {
|
||||||
|
byte[] key = new byte[18];
|
||||||
|
random.nextBytes(key);
|
||||||
|
|
||||||
|
AccessKey accessKey = new AccessKey();
|
||||||
|
accessKey.key = key;
|
||||||
|
accessKey.account = account;
|
||||||
|
accessKey.accessLimits = accessLimits;
|
||||||
|
accessKey.persist();
|
||||||
|
|
||||||
|
return Base64.getEncoder().encodeToString(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package eu.m724.orm;
|
||||||
|
|
||||||
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToOne;
|
|
||||||
|
|
||||||
//@Entity
|
//@Entity
|
||||||
public class AccessKey extends PanacheEntity {
|
public class AccessKey extends PanacheEntity {
|
||||||
|
@ -20,6 +19,5 @@ public class AccessKey extends PanacheEntity {
|
||||||
/**
|
/**
|
||||||
* access limits of this key
|
* access limits of this key
|
||||||
*/
|
*/
|
||||||
@OneToOne
|
|
||||||
public AccessLimits accessLimits;
|
public AccessLimits accessLimits;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,10 @@ package eu.m724.orm;
|
||||||
|
|
||||||
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.Entity;
|
||||||
|
|
||||||
//@Entity
|
@Entity
|
||||||
public class AccessLimits extends PanacheEntity {
|
public class AccessLimits extends PanacheEntity {
|
||||||
@OneToOne
|
|
||||||
public AccessKey accessKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* label of these limits, displayed to user and used to identify the limits
|
* label of these limits, displayed to user and used to identify the limits
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,10 @@ import io.quarkus.hibernate.orm.panache.PanacheEntity;
|
||||||
import io.quarkus.security.jpa.Roles;
|
import io.quarkus.security.jpa.Roles;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
// TODO organize all this like work on variable names move functions etc
|
// TODO organize all this like work on variable names move functions etc
|
||||||
|
|
||||||
|
@ -12,8 +16,8 @@ public class Account extends PanacheEntity {
|
||||||
@Column(unique = true)
|
@Column(unique = true)
|
||||||
public byte[] masterKey;
|
public byte[] masterKey;
|
||||||
|
|
||||||
//@OneToMany
|
@OneToMany
|
||||||
//public List<AccessKey> accessKeys = new ArrayList<>();
|
public List<AccessKey> accessKeys = new ArrayList<>();
|
||||||
|
|
||||||
@Roles
|
@Roles
|
||||||
public String role = "user";
|
public String role = "user";
|
||||||
|
|
Loading…
Reference in a new issue