Skip to content

Commit

Permalink
Finished client side service-desk #587
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Jan 20, 2025
1 parent 41ea2ae commit 47d1489
Show file tree
Hide file tree
Showing 70 changed files with 2,152 additions and 969 deletions.
2 changes: 1 addition & 1 deletion myconext-gui/docker/conf/000-default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ DocumentRoot "/var/www"
Require all granted
</Location>

<Location ~ "/create-from-institution(.*)">
<Location ~ "^/(?!startSSO)">
Require all granted
</Location>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.HttpServletRequest;
import myconext.exceptions.RemoteException;
import myconext.exceptions.UserNotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand Down Expand Up @@ -76,6 +77,9 @@ public ResponseEntity error(HttpServletRequest request) throws URISyntaxExceptio
} else {
statusCode = BAD_REQUEST;
}
if (error instanceof RemoteException) {
result.put("reference", ((RemoteException)error).getReference());
}
}
result.put("status", statusCode.value());
return ResponseEntity.status(statusCode).body(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public LoginController(UserRepository userRepository,
public Map<String, Object> config() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Map<String ,Object> copyConfig = new HashMap<>(config);
//Can be an AnonymousAuthenticationToken with Principal=anonymousUser
boolean authenticated = authentication != null && authentication.isAuthenticated() && authentication.getPrincipal() instanceof User;
copyConfig.put("authenticated", authenticated);
if (authenticated ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.Getter;
import myconext.exceptions.ForbiddenException;
import myconext.exceptions.RemoteException;
import myconext.exceptions.UserNotFoundException;
import myconext.model.ControlCode;
import myconext.model.ExternalLinkedAccount;
Expand All @@ -11,6 +12,7 @@
import myconext.verify.AttributeMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
Expand Down Expand Up @@ -56,8 +58,19 @@ public ResponseEntity<Boolean> validateDate(@RequestParam("dayOfBirth") String d
}

@PutMapping("/approve")
public ResponseEntity<Void> convertUserControlCode(Authentication authentication,
public ResponseEntity<ExternalLinkedAccount> convertUserControlCode(Authentication authentication,
@RequestBody ControlCode controlCode) {
try {
return doConvertUserControlCode(authentication, controlCode);
} catch (RuntimeException e) {
ResponseStatus annotation = AnnotationUtils.getAnnotation(e.getClass(), ResponseStatus.class);
HttpStatus status = annotation != null ? annotation.value() : HttpStatus.BAD_REQUEST;
//This will log the reference to correlate to the user mail
throw new RemoteException(status, e.getMessage(), e);
}
}

private ResponseEntity<ExternalLinkedAccount> doConvertUserControlCode(Authentication authentication, ControlCode controlCode) throws RuntimeException{
String code = controlCode.getCode();
User user = userRepository.findByControlCode_Code(code)
.orElseThrow(() -> new UserNotFoundException(String.format("No user found with controlCode %s", code)));
Expand All @@ -69,16 +82,20 @@ public ResponseEntity<Void> convertUserControlCode(Authentication authentication
throw new ForbiddenException("User UID's do not match");
}

User serviceDeskMember = userFromAuthentication(authentication);
String userUid = ((User) authentication.getPrincipal()).getUid();
User serviceDeskMember = getUserRepository().findUserByUid(userUid).orElseThrow(() -> new UserNotFoundException(userUid));

LOG.info(String.format("Adding external linked account for service desk for user %s by user %s",
user.getEmail(), serviceDeskMember.getEmail()));

ExternalLinkedAccount externalLinkedAccount = attributeMapper.createFromControlCode(controlCode);
user.getExternalLinkedAccounts().add(externalLinkedAccount);
//The controlCode is now invalid as already used
user.setControlCode(null);

userRepository.save(user);

return ResponseEntity.status(HttpStatus.CREATED).build();
return ResponseEntity.status(HttpStatus.CREATED).body(externalLinkedAccount);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package myconext.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

public class RemoteException extends ResponseStatusException {

private final String reference;

public RemoteException(HttpStatus status, String reason, Throwable cause) {
super(status, reason, cause);
this.reference = String.valueOf(Math.round(Math.random() * 10000));
}

public String getReference() {
return reference;
}

@Override
public String toString() {
return "reference='" + reference + "' " + super.toString();
}
}
2 changes: 2 additions & 0 deletions myconext-server/src/main/java/myconext/model/ControlCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class ControlCode implements Serializable {
@Setter
@Indexed
private String code;

private String documentId;
@Setter
private long createdAt;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ void convertUserControlCode() {

User user = userRepository.findOneUserByEmail("[email protected]");
assertEquals(1, user.getExternalLinkedAccounts().size());
assertNull(user.getControlCode());

ExternalLinkedAccount externalLinkedAccount = user.getExternalLinkedAccounts().getFirst();
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder().appendPattern("dd-MM-yyyy").toFormatter();
Expand Down
4 changes: 4 additions & 0 deletions servicedesk-gui/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM ghcr.io/openconext/openconext-basecontainers/apache2-shibboleth:latest
COPY ./dist/ /var/www/
COPY ./docker/conf/000-default.conf /etc/apache2/sites-enabled/000-default.conf

88 changes: 88 additions & 0 deletions servicedesk-gui/docker/conf/000-default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
ServerName https://${HTTPD_SERVERNAME}
RewriteEngine on

RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.(js|css)(\.map)?$
RewriteCond %{REQUEST_URI} !\.svg$
RewriteCond %{REQUEST_URI} !\.png$
RewriteCond %{REQUEST_URI} !\.ico$
RewriteCond %{REQUEST_URI} !\.woff$
RewriteCond %{REQUEST_URI} !\.woff2$
RewriteCond %{REQUEST_URI} !\.ttf$
RewriteCond %{REQUEST_URI} !\.eot$
RewriteCond %{REQUEST_URI} !^/(asset-)?manifest.json$
RewriteCond %{REQUEST_URI} !^/myconext
RewriteCond %{REQUEST_URI} !^/tiqr
RewriteCond %{REQUEST_URI} !^/actuator
RewriteCond %{REQUEST_URI} !^/internal
RewriteCond %{REQUEST_URI} !^/robots.txt
RewriteCond %{REQUEST_URI} !^/config
RewriteCond %{REQUEST_URI} !^/login
RewriteCond %{REQUEST_URI} !^/startSSO
RewriteCond %{REQUEST_URI} !^/fonts
RewriteCond %{REQUEST_URI} !^/.well-known
RewriteRule (.*) /index.html [L]

ProxyPreserveHost On
ProxyPass /Shibboleth.sso !

ProxyPass /myconext/api http://myconextserver:8080/myconext/api
ProxyPassReverse /myconext/api http://myconextserver:8080/myconext/api

ProxyPass /tiqr http://myconextserver:8080/tiqr
ProxyPassReverse /tiqr http://myconextserver:8080/tiqr

ProxyPass /internal http://myconextserver:8080/internal
ProxyPass /actuator http://myconextserver:8080/internal
ProxyPass /robots.txt http://myconextserver:8080/robots.txt
ProxyPass /login http://myconextserver:8080/login
ProxyPass /startSSO http://myconextserver:8080/startSSO
ProxyPass /config http://myconextserver:8080/config

<Location />
AuthType shibboleth
ShibUseHeaders On
ShibRequireSession On
Require valid-user
</Location>

DocumentRoot "/var/www"

<Directory "/var/www">
Require all granted
Options -Indexes
</Directory>

# Public endpoints
<Location ~ "/(config|register|404|robots.txt)">
Require all granted
</Location>

<Location ~ "/landing(.*)">
Require all granted
</Location>

<Location ~ "/(.*)">
Require all granted
</Location>

<Location ~ "/internal/">
Require all granted
</Location>

# React resources
<Location ~ "(.*)(eot|svg|ttf|woff2|woff|js|js\.map|css|css\.map|png|jpg|ico)$">
Require all granted
</Location>

<Location ~ "/.well-known/">
Require all granted
</Location>

<Location ~ "/(asset-)?manifest.json$">
Require all granted
</Location>

Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "same-origin"
Header always set X-Content-Type-Options "nosniff"
61 changes: 33 additions & 28 deletions servicedesk-gui/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,39 @@ import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
{
'extends': [
'plugin:react/recommended'
]
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
{ignores: ['dist']},
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: {jsx: true},
sourceType: 'module',
},
},
settings: {react: {version: '18.3'}},
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{allowConstantExport: true},
],
},
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
2 changes: 1 addition & 1 deletion servicedesk-gui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ServiceDesk</title>
</head>
<body class="sds--color-palette--green">
<body class="sds--color-palette--blue">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
Expand Down
6 changes: 4 additions & 2 deletions servicedesk-gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
"preview": "vite preview",
"test": "vitest"
},
"dependencies": {
"@surfnet/sds": "^0.0.120",
"@surfnet/sds": "^0.0.126",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "7.1.0",
Expand All @@ -34,6 +35,7 @@
"globals": "^15.14.0",
"sass": "^1.83.0",
"vite": "^6.0.4",
"vitest": "^3.0.2",
"http-proxy-middleware": "^3.0.3"
}
}
Loading

0 comments on commit 47d1489

Please sign in to comment.