Compare commits

..

No commits in common. "2542e3f05eded7d6da19006fa8de583bae7c3b02" and "63f705e6930c8385bb4ff46c8d383d2f1ead6fbf" have entirely different histories.

9 changed files with 136 additions and 133 deletions

View file

@ -1,10 +1,62 @@
# rwws - RealWeather Web Server
# rwws
This contacts APIs instead of the servers because we scrape some and we don't want to draw attention
This project uses Quarkus, the Supersonic Subatomic Java Framework.
### Usage
See `RUNNING.md`[^1]
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
---
## Running the application in dev mode
[^1]: This is the default Quarkus readme that I wish was available online
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 its 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)

View file

@ -1,62 +0,0 @@
# 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 its 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)

View file

@ -16,11 +16,11 @@ public class Startup {
AccountService accountService;
@Transactional
public void loadUsers(@Observes StartupEvent ignoredEvent) {
public void loadUsers(@Observes StartupEvent event) {
Account.deleteAll();
byte[] adminKey = new byte[18];
accountService.add(adminKey, "admin");
UserManager.add(adminKey, "admin");
System.out.println("Admin user created: " + Base64.getEncoder().encodeToString(adminKey));
}
}

View file

@ -0,0 +1,65 @@
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);
}
}

View file

@ -1,6 +1,5 @@
package eu.m724;
import eu.m724.auth.master.AccountService;
import eu.m724.orm.Account;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.annotation.security.RolesAllowed;
@ -18,14 +17,11 @@ public class UsersResource {
@Inject
SecurityIdentity securityIdentity;
@Inject
AccountService accountService;
@GET
@Path("/create")
@RolesAllowed("admin")
public JsonObject createAccount() {
String masterKey = accountService.create("user");
String masterKey = UserManager.create();
return Json.createObjectBuilder()
.add("masterKey", masterKey)

View file

@ -1,18 +1,13 @@
package eu.m724.auth.master;
import eu.m724.orm.AccessKey;
import eu.m724.orm.AccessLimits;
import eu.m724.orm.Account;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import java.security.SecureRandom;
import java.util.Base64;
@ApplicationScoped
public class AccountService {
private final SecureRandom random = new SecureRandom();
/**
* find a master user by key
* @param key base64 encoded key
@ -23,53 +18,9 @@ public class AccountService {
if (key == null) return null;
try {
return Account.find("masterKey", (Object) Base64.getDecoder().decode(key)).firstResult();
return Account.find("masterKey", Base64.getDecoder().decode(key)).firstResult();
} catch (IllegalArgumentException e) {
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);
}
}

View file

@ -2,6 +2,7 @@ package eu.m724.orm;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
//@Entity
public class AccessKey extends PanacheEntity {
@ -19,5 +20,6 @@ public class AccessKey extends PanacheEntity {
/**
* access limits of this key
*/
@OneToOne
public AccessLimits accessLimits;
}

View file

@ -2,10 +2,13 @@ package eu.m724.orm;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.OneToOne;
@Entity
//@Entity
public class AccessLimits extends PanacheEntity {
@OneToOne
public AccessKey accessKey;
/**
* label of these limits, displayed to user and used to identify the limits
*/

View file

@ -4,10 +4,6 @@ import io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.security.jpa.Roles;
import jakarta.persistence.Column;
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
@ -16,8 +12,8 @@ public class Account extends PanacheEntity {
@Column(unique = true)
public byte[] masterKey;
@OneToMany
public List<AccessKey> accessKeys = new ArrayList<>();
//@OneToMany
//public List<AccessKey> accessKeys = new ArrayList<>();
@Roles
public String role = "user";