1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.graphql.command;
23
24 import org.opencastproject.authorization.xacml.manager.api.AclService;
25 import org.opencastproject.authorization.xacml.manager.api.AclServiceFactory;
26 import org.opencastproject.elasticsearch.api.SearchIndexException;
27 import org.opencastproject.elasticsearch.index.ElasticsearchIndex;
28 import org.opencastproject.graphql.exception.GraphQLNotFoundException;
29 import org.opencastproject.graphql.exception.GraphQLRuntimeException;
30 import org.opencastproject.graphql.exception.GraphQLUnauthorizedException;
31 import org.opencastproject.graphql.execution.context.OpencastContext;
32 import org.opencastproject.graphql.execution.context.OpencastContextManager;
33 import org.opencastproject.graphql.series.GqlSeries;
34 import org.opencastproject.graphql.type.input.AccessControlListInput;
35 import org.opencastproject.graphql.type.input.GqlCommonSeriesMetadataInput;
36 import org.opencastproject.graphql.util.GraphQLObjectMapper;
37 import org.opencastproject.index.service.api.IndexService;
38 import org.opencastproject.index.service.catalog.adapter.series.CommonSeriesCatalogUIAdapter;
39 import org.opencastproject.index.service.exception.IndexServiceException;
40 import org.opencastproject.mediapackage.MediaPackageElementFlavor;
41 import org.opencastproject.metadata.dublincore.DublinCoreMetadataCollection;
42 import org.opencastproject.metadata.dublincore.MetadataField;
43 import org.opencastproject.metadata.dublincore.MetadataList;
44 import org.opencastproject.security.api.AccessControlEntry;
45 import org.opencastproject.security.api.AccessControlList;
46 import org.opencastproject.security.api.SecurityService;
47 import org.opencastproject.security.api.UnauthorizedException;
48 import org.opencastproject.series.api.SeriesException;
49 import org.opencastproject.series.api.SeriesService;
50 import org.opencastproject.util.NotFoundException;
51
52 import java.util.Map;
53
54 public class UpdateSeriesCommand extends AbstractCommand<GqlSeries> {
55
56 private final String seriesId;
57
58 public UpdateSeriesCommand(final Builder builder) {
59 super(builder);
60 this.seriesId = builder.seriesId;
61 }
62
63 @Override
64 public GqlSeries execute() {
65 OpencastContext context = OpencastContextManager.getCurrentContext();
66 final ElasticsearchIndex index = context.getService(ElasticsearchIndex.class);
67 final IndexService indexService = context.getService(IndexService.class);
68
69 final Map<String, Object> seriesMetadata = environment.getArgument("metadata");
70 try {
71 indexService.updateAllSeriesMetadata(this.seriesId,
72 createMetadataList(seriesMetadata, indexService), index);
73 } catch (IndexServiceException e) {
74 throw new GraphQLRuntimeException(e);
75 } catch (UnauthorizedException e) {
76 throw new GraphQLUnauthorizedException(e.getMessage());
77 } catch (NotFoundException e) {
78 throw new GraphQLNotFoundException(e.getMessage());
79 }
80
81 final SeriesService seriesService = context.getService(SeriesService.class);
82
83 final AccessControlListInput aclInput = GraphQLObjectMapper.newInstance()
84 .convertValue(environment.getArgument("acl"), AccessControlListInput.class);
85 if (aclInput != null) {
86 try {
87 AccessControlList acl = new AccessControlList();
88 for (var entry : aclInput.getEntries()) {
89 for (var action : entry.getAction()) {
90 acl.getEntries().add(new AccessControlEntry(entry.getRole(), action, true));
91 }
92 }
93
94 if (aclInput.getManagedAclId() != null) {
95 AclService aclService = context.getService(AclServiceFactory.class)
96 .serviceFor(context.getService(SecurityService.class).getOrganization());
97 aclService.getAcl(aclInput.getManagedAclId())
98 .ifPresent(value -> acl.merge(value.getAcl()));
99 }
100 seriesService.updateAccessControl(seriesId, acl);
101 } catch (UnauthorizedException e) {
102 throw new GraphQLUnauthorizedException(e.getMessage());
103 } catch (NotFoundException e) {
104 throw new GraphQLNotFoundException(e.getMessage());
105 } catch (SeriesException e) {
106 throw new GraphQLRuntimeException(e);
107 }
108 }
109
110 try {
111 return new GqlSeries(
112 index.getSeries(seriesId, context.getOrganization().getId(), context.getUser()).get()
113 );
114 } catch (SearchIndexException e) {
115 throw new GraphQLRuntimeException(e);
116 }
117 }
118
119 private MetadataList createMetadataList(Map<String, Object> seriesMetadata, IndexService indexService) {
120 CommonSeriesCatalogUIAdapter adapter = (CommonSeriesCatalogUIAdapter) indexService
121 .getCommonSeriesCatalogUIAdapter();
122
123 MetadataList list = new MetadataList();
124 list.add(adapter, adapter.getRawFields());
125
126 final MediaPackageElementFlavor flavor = MediaPackageElementFlavor
127 .parseFlavor("dublincore/series");
128
129 final DublinCoreMetadataCollection collection = list.getMetadataByFlavor(flavor.toString());
130
131 seriesMetadata.keySet().forEach(k -> {
132 final MetadataField target = collection.getOutputFields().get(k);
133 target.setValue(seriesMetadata.get(k));
134 });
135
136 return list;
137 }
138
139 public static Builder create(String seriesId, GqlCommonSeriesMetadataInput seriesMetadataInput) {
140 return new Builder(seriesId, seriesMetadataInput);
141 }
142
143 public static class Builder extends AbstractCommand.Builder<GqlSeries> {
144
145 private final String seriesId;
146
147 private final GqlCommonSeriesMetadataInput seriesMetadataInput;
148
149
150 public Builder(String seriesId, GqlCommonSeriesMetadataInput seriesMetadataInput) {
151 this.seriesId = seriesId;
152 this.seriesMetadataInput = seriesMetadataInput;
153 }
154
155 @Override
156 public void validate() {
157 super.validate();
158 if (seriesId == null || seriesId.isEmpty()) {
159 throw new IllegalStateException("Series ID cannot be null or empty");
160 }
161 if (seriesMetadataInput == null) {
162 throw new IllegalStateException("Series metadata cannot be null");
163 }
164 }
165
166 @Override
167 public UpdateSeriesCommand build() {
168 validate();
169 return new UpdateSeriesCommand(this);
170 }
171 }
172
173 }