• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FIWARE / credentials-config-service / #35

07 May 2025 10:37AM UTC coverage: 81.545% (+0.3%) from 81.223%
#35

Pull #10

wistefan
make jwt inclusion optional
Pull Request #10: temp support for tech-x

2 of 2 new or added lines in 1 file covered. (100.0%)

10 existing lines in 2 files now uncovered.

190 of 233 relevant lines covered (81.55%)

0.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.1
/src/main/java/org/fiware/iam/rest/ServiceApiController.java
1
package org.fiware.iam.rest;
2

3
import io.micronaut.core.annotation.Introspected;
4
import io.micronaut.core.annotation.NonNull;
5
import io.micronaut.core.annotation.Nullable;
6
import io.micronaut.data.model.Page;
7
import io.micronaut.data.model.Pageable;
8
import io.micronaut.data.model.Sort;
9
import io.micronaut.http.HttpResponse;
10
import io.micronaut.http.annotation.Controller;
11
import lombok.RequiredArgsConstructor;
12
import lombok.extern.slf4j.Slf4j;
13
import org.fiware.iam.ServiceMapper;
14
import org.fiware.iam.ccs.api.ServiceApi;
15
import org.fiware.iam.ccs.model.*;
16
import org.fiware.iam.exception.ConflictException;
17
import org.fiware.iam.repository.Service;
18
import org.fiware.iam.repository.ServiceRepository;
19

20
import javax.transaction.Transactional;
21
import java.net.URI;
22
import java.util.Optional;
23

24
/**
25
 * Implementation of the service api to configure services and there credentials
26
 */
27
@Slf4j
1✔
28
@Controller("${general.basepath:/}")
29
@RequiredArgsConstructor
30
@Introspected
31
public class ServiceApiController implements ServiceApi {
32

33
    private final ServiceRepository serviceRepository;
34
    private final ServiceMapper serviceMapper;
35

36
    @Override
37
    public HttpResponse<Object> createService(@NonNull ServiceVO serviceVO) {
38
        if (serviceVO.getId() != null && serviceRepository.existsById(serviceVO.getId())) {
1✔
39
            throw new ConflictException(String.format("The service with id %s already exists.", serviceVO.getId()),
1✔
40
                    serviceVO.getId());
1✔
41
        }
42
        validateServiceVO(serviceVO);
1✔
43

44
        Service mappedService = serviceMapper.map(serviceVO);
1✔
45
        Service savedService = serviceRepository.save(mappedService);
1✔
46

47
        return HttpResponse.created(
1✔
48
                URI.create(
1✔
49
                        ServiceApi.PATH_GET_SERVICE.replace(
1✔
50
                                "{id}", savedService.getId())));
1✔
51
    }
52

53
    @Override
54
    public HttpResponse<Object> deleteServiceById(@NonNull String id) {
55
        if (!serviceRepository.existsById(id)) {
1✔
56
            return HttpResponse.notFound();
1✔
57
        }
58
        serviceRepository.deleteById(id);
1✔
59
        return HttpResponse.noContent();
1✔
60
    }
61

62
    @Override
63
    public HttpResponse<ScopeVO> getScopeForService(@NonNull String id, @Nullable String oidcScope) {
64
        Optional<Service> service = serviceRepository.findById(id);
1✔
65
        if (service.isEmpty()) {
1✔
66
            return HttpResponse.notFound();
1✔
67
        }
68
        String selectedOidcScope =
69
                oidcScope == null ?
1✔
70
                        serviceMapper.map(service.get()).getDefaultOidcScope() :
1✔
71
                        oidcScope;
1✔
72
        ServiceScopesEntryVO serviceScopesEntryVO = serviceMapper.map(service.get())
1✔
73
                .getOidcScopes()
1✔
74
                .get(selectedOidcScope);
1✔
75
        ScopeVO scopeVO = new ScopeVO();
1✔
76
        scopeVO.addAll(serviceScopesEntryVO.stream().map(CredentialVO::getType).toList());
1✔
77
        return HttpResponse.ok(scopeVO);
1✔
78
    }
79

80
    @Override
81
    public HttpResponse<ServiceVO> getService(@NonNull String id) {
82
        return serviceRepository.findById(id)
1✔
83
                .map(serviceMapper::map)
1✔
84
                .map(HttpResponse::ok)
1✔
85
                .orElse(HttpResponse.notFound());
1✔
86
    }
87

88
    @Override
89
    public HttpResponse<ServicesVO> getServices(@Nullable Integer nullablePageSize,
90
                                                @Nullable Integer nullablePage) {
91
        var pageSize = Optional.ofNullable(nullablePageSize).orElse(100);
1✔
92
        var page = Optional.ofNullable(nullablePage).orElse(0);
1✔
93
        if (pageSize < 1) {
1✔
94
            throw new IllegalArgumentException("PageSize has to be at least 1.");
1✔
95
        }
96
        if (page < 0) {
1✔
97
            throw new IllegalArgumentException("Offsets below 0 are not supported.");
1✔
98
        }
99

100
        Page<Service> requestedPage = serviceRepository.findAll(
1✔
101
                Pageable.from(page, pageSize, Sort.of(Sort.Order.asc("id"))));
1✔
102
        return HttpResponse.ok(
1✔
103
                new ServicesVO()
104
                        .total((int) requestedPage.getTotalSize())
1✔
105
                        .pageNumber(page)
1✔
106
                        .pageSize(requestedPage.getContent().size())
1✔
107
                        .services(requestedPage.getContent().stream().map(serviceMapper::map).toList()));
1✔
108
    }
109

110
    @Transactional
111
    @Override
112
    public HttpResponse<ServiceVO> updateService(@NonNull String id, @NonNull ServiceVO serviceVO) {
113
        if (serviceVO.getId() != null && !id.equals(serviceVO.getId())) {
1✔
UNCOV
114
            throw new IllegalArgumentException("The id of a service cannot be updated.");
×
115
        }
116
        validateServiceVO(serviceVO);
1✔
117
        if (!serviceRepository.existsById(id)) {
1✔
118
            return HttpResponse.notFound();
1✔
119
        }
120
        // just in case none is set in the object
121
        serviceVO.setId(id);
1✔
122
        serviceRepository.deleteById(id);
1✔
123
        return HttpResponse.ok(serviceMapper.map(serviceRepository.save(serviceMapper.map(serviceVO))));
1✔
124
    }
125

126
    // validate a service vo, e.g. check forbidden null values
127
    private void validateServiceVO(ServiceVO serviceVO) {
128
        if (serviceVO.getDefaultOidcScope() == null) {
1✔
129
            throw new IllegalArgumentException("Default OIDC scope cannot be null.");
1✔
130
        }
131
        if (serviceVO.getOidcScopes() == null) {
1✔
132
            throw new IllegalArgumentException("OIDC scopes cannot be null.");
1✔
133
        }
134

135
        String defaultOidcScope = serviceVO.getDefaultOidcScope();
1✔
136
        ServiceScopesEntryVO serviceScopesEntryVO = serviceVO
1✔
137
                .getOidcScopes()
1✔
138
                .get(defaultOidcScope);
1✔
139
        if (serviceScopesEntryVO == null) {
1✔
UNCOV
140
            throw new IllegalArgumentException("Default OIDC scope must exist in OIDC scopes array.");
×
141
        }
142

143
        Optional<CredentialVO> nullType = serviceScopesEntryVO
1✔
144
                .stream()
1✔
145
                .filter(cvo -> cvo.getType() == null)
1✔
146
                .findFirst();
1✔
147
        if (nullType.isPresent()) {
1✔
148
            throw new IllegalArgumentException("Type of a credential cannot be null.");
1✔
149
        }
150
    }
1✔
151

152
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc