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

IQSS / dataverse / #22002

01 Apr 2024 07:56PM CUT coverage: 20.716% (+0.5%) from 20.173%
#22002

push

github

web-flow
Merge pull request #10453 from IQSS/develop

Merge 6.2 into master

704 of 2679 new or added lines in 152 files covered. (26.28%)

81 existing lines in 49 files now uncovered.

17160 of 82836 relevant lines covered (20.72%)

0.21 hits per line

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

0.0
/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/CreateNewDatasetCommand.java
1
package edu.harvard.iq.dataverse.engine.command.impl;
2

3
import edu.harvard.iq.dataverse.Dataset;
4
import edu.harvard.iq.dataverse.DatasetVersion;
5
import edu.harvard.iq.dataverse.Dataverse;
6
import edu.harvard.iq.dataverse.GlobalId;
7
import edu.harvard.iq.dataverse.RoleAssignment;
8
import edu.harvard.iq.dataverse.Template;
9
import edu.harvard.iq.dataverse.UserNotification;
10
import edu.harvard.iq.dataverse.authorization.Permission;
11
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
12
import edu.harvard.iq.dataverse.engine.command.CommandContext;
13
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
14
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
15
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
16
import edu.harvard.iq.dataverse.pidproviders.PidProvider;
17
import edu.harvard.iq.dataverse.pidproviders.PidUtil;
18
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
19

20
import static edu.harvard.iq.dataverse.util.StringUtil.nonEmpty;
21
import java.util.logging.Logger;
22

23
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
24
import java.util.List;
25
import java.sql.Timestamp;
26
import java.time.Instant;
27

28
/**
29
 * Creates a new {@link Dataset}, used to store unpublished data. This is as opposed to 
30
 * a harvested or imported datasets, which may contain data that was already published 
31
 * when they are created.
32
 * 
33
 * @author michael
34
 */
35
@RequiredPermissions(Permission.AddDataset)
36
// I am reverting the PR #6061, going back to the fixed RequiredPermissions that 
37
// specifies the AddDataset to be the only permission needed. We tried to 
38
// replace it with a dynamic permissions map, with the extra ViewUnpublishedDataverse
39
// permission added when the Dataverse is unpublished (to prevent any user with a 
40
// Dataverse account from adding datasets to a dataverse so configured, before it's 
41
// published). This caused too many unexpected complications - the most notable
42
// one with the SWORD API (a bunch of RestAssured tests apparently rely on this 
43
// ability). 
44
// In order to re-enable the dynamic permissions, comment out the RequiredPermissions
45
// line above, AND un-comment out the getRequiredPermissions() method below. 
46

47
public class CreateNewDatasetCommand extends AbstractCreateDatasetCommand {
48
    private static final Logger logger = Logger.getLogger(CreateNewDatasetCommand.class.getName());
×
49
    
50
    private final Template template;
51
    private final Dataverse dv;
52

53
    public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest) {
54
        this( theDataset, aRequest, null);
×
55
    }
×
56
    
57
    public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest, Template template) {
58
        super(theDataset, aRequest);
×
59
        this.template = template;
×
60
        dv = theDataset.getOwner();
×
61
    }
×
62
    
63
    public CreateNewDatasetCommand(Dataset theDataset, DataverseRequest aRequest, Template template, boolean validate) {
64
        super(theDataset, aRequest, false, validate);
×
65
        this.template = template;
×
66
        dv = theDataset.getOwner();
×
67
    }
×
68
    
69
    /**
70
     * A new dataset must have a new identifier.
71
     * @param ctxt
72
     * @throws CommandException 
73
     */
74
    @Override
75
    protected void additionalParameterTests(CommandContext ctxt) throws CommandException {
NEW
76
        if (nonEmpty(getDataset().getIdentifier())) {
×
NEW
77
            GlobalId pid = getDataset().getGlobalId();
×
NEW
78
            if (pid != null) {
×
NEW
79
                PidProvider pidProvider = PidUtil.getPidProvider(pid.getProviderId());
×
80

NEW
81
                if (!pidProvider.isGlobalIdUnique(pid)) {
×
NEW
82
                    throw new IllegalCommandException(String.format(
×
83
                            "Dataset with identifier '%s', protocol '%s' and authority '%s' already exists",
NEW
84
                            getDataset().getIdentifier(), getDataset().getProtocol(), getDataset().getAuthority()),
×
85
                            this);
86
                }
87
            }
88
        }
89
    }
×
90
    
91
    @Override
92
    protected DatasetVersion getVersionToPersist( Dataset theDataset ) {
93
        return theDataset.getOrCreateEditVersion();
×
94
    }
95

96
    @Override
97
    protected void handlePid(Dataset theDataset, CommandContext ctxt) throws CommandException {
NEW
98
        PidProvider pidProvider = PidUtil.getPidProvider(theDataset.getGlobalId().getProviderId());
×
NEW
99
        if(!pidProvider.canManagePID()) {
×
NEW
100
            throw new IllegalCommandException("PID Provider " + pidProvider.getId() + " is not configured.", this);
×
101
        }
NEW
102
        if ( !pidProvider.registerWhenPublished() ) {
×
103
            // pre-register a persistent id
104
            registerExternalIdentifier(theDataset, ctxt, true);
×
105
        }
106
    }
×
107
    
108
    @Override
109
    protected void postPersist( Dataset theDataset, CommandContext ctxt ){
110
        // set the role to be default contributor role for its dataverse
111
        String privateUrlToken = null;
×
112
        if (theDataset.getOwner().getDefaultContributorRole() != null) {
×
113
            RoleAssignment roleAssignment = new RoleAssignment(theDataset.getOwner().getDefaultContributorRole(),
×
114
                    getRequest().getUser(), theDataset, privateUrlToken);
×
115
            ctxt.roles().save(roleAssignment, false);
×
116

117
            // TODO: the above may be creating the role assignments and saving them 
118
            // in the database, but without properly linking them to the dataset
119
            // (saveDataset, that the command returns). This may have been the reason 
120
            // for the github issue #4783 - where the users were losing their contributor
121
            // permissions, when creating datasets AND uploading files in one step. 
122
            // In that scenario, an additional UpdateDatasetCommand is exectued on the
123
            // dataset returned by the Create command. That issue was fixed by adding 
124
            // a full refresh of the datast with datasetService.find() between the 
125
            // two commands. But it may be a good idea to make sure they are properly
126
            // linked here (?)
127
            theDataset.setPermissionModificationTime(getTimestamp());
×
128
        }
129
        
130
        if ( template != null ) {
×
131
            ctxt.templates().incrementUsageCount(template.getId());
×
132
        }
133
    }
×
134
    
135
    /* Emails those able to publish the dataset (except the creator themselves who already gets an email)
136
     * that a new dataset exists. 
137
     * NB: Needs dataset id so has to be postDBFlush (vs postPersist())
138
     */
139
    protected void postDBFlush( Dataset theDataset, CommandContext ctxt ){
140
        if(ctxt.settings().isTrueForKey(SettingsServiceBean.Key.SendNotificationOnDatasetCreation, false)) {
×
141
        //QDR - alert curators that a dataset has been created
142
        //Should this create a notification too? (which would let us use the notification mailcapbilities to generate the subject/body.
143
        AuthenticatedUser requestor = getUser().isAuthenticated() ? (AuthenticatedUser) getUser() : null;
×
144
        List<AuthenticatedUser> authUsers = ctxt.permissions().getUsersWithPermissionOn(Permission.PublishDataset, theDataset);
×
145
        for (AuthenticatedUser au : authUsers) {
×
146
            if(!au.equals(requestor)) {
×
147
                ctxt.notifications().sendNotification(
×
148
                        au,
149
                        Timestamp.from(Instant.now()),
×
150
                        UserNotification.Type.DATASETCREATED,
151
                        theDataset.getId(),
×
152
                        null,
153
                        requestor,
154
                        true
155
                );
156
            }
157
        }
×
158
        }
159
    }
×
160
    
161
    // Re-enabling the method below will change the permission setup to dynamic.
162
    // This will make it so that in an unpublished dataverse only users with the 
163
    // permission to view it will be allowed to create child datasets. 
164
    /*@Override
165
    public Map<String, Set<Permission>> getRequiredPermissions() {
166
        Map<String, Set<Permission>> ret = new HashMap<>();
167
        // NOTE: DO NOT use builtin methods such as 
168
        // Collections.singleton(Permission.AddDataset) in order to create 
169
        // permission HashSets. Collections.singleton() produces a set that is 
170
        // *unmutable* - and you should assume that the set may need to be 
171
        // modified later on. For example, as follows, in the 
172
        // hasGroupPermissionsFor() method in PermissionServiceBean:
173
        // 
174
        // for (RoleAssignment asmnt : assignmentsFor(ras, dvo)) {
175
        //    required.removeAll(asmnt.getRole().permissions());
176
        // }
177
        // return required.isEmpty();
178
        ret.put("", new HashSet<>(Arrays.asList(Permission.AddDataset)));
179
        if (!dv.isReleased()) {
180
            ret.get("").add(Permission.ViewUnpublishedDataverse);
181
        }
182
        return ret;
183
    }*/
184
        
185
}
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

© 2025 Coveralls, Inc